Страницы

Поиск по вопросам

воскресенье, 9 июня 2019 г.

Как работает команда `nginx` если её нет в $PATH?

$ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
$ whereis -b nginx nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
Исполняемый файл находится здесь: /usr/sbin/nginx, но /usr/sbin нет в $PATH.


Ответ

от имени «рядового» пользователя:
$ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
от имени пользователя с идентификатором 0 (обычно у него имя root):
$ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

как видите, во втором случае в переменной окружения PATH присутствует каталог /usr/sbin
поэтому команда nginx, выполненная от имени «рядового» пользователя, не приведёт к запуску программы nginx из файла /usr/sbin/nginx. а от имени пользователя с именем root — приведёт.

дополнение из комментариев:
А как же рядовой пользователь запускает nginx -t для проверки корректности конфига? При этом проверка работает как от root'а, так и от рядового пользователя (разве может ругнуться на SSL сертификат). Не знаю, что там в дебианах, но в центосе спокойно можно запустить (я правда не обращал внимания на PATH)
либо этот пользователь указывает всё-таки полный путь к файлу, либо переменная окружения PATH (хотя бы в момент выполнения команды) содержит путь к этому файлу, либо запускается какой-то другой файл, расположенный не в каталоге /usr/sbin, либо запускается функция/псевдоним оболочки (которая впоследствии запускает файл уже по абсолютному пути).

доп. чтение.
механизм поиска и выполнения программ описан в стандарте posix к сожалению, стандарт posix не содержит каких-либо указаний по поводу функционального распределения файлов/каталогам по файловой системе. поэтому надо смотреть в документацию соответствующих реализаций стандарта:
unix и наследники gnu/linux

DrawingVisual в фоновом потоке С# WPF 3.5

В фоновом потоке формирую матрицу случайными числами:
public void Step() { Point p; Brush b; Random r = new Random();
for (int i = 0; i < mh; i++) { for (int j = 0; j < mw; j++) { p = new Point(i*5, j*5); int ch = r.Next(0, 100); if (ch <= 33) { b = Brushes.Green; vl.Add(new VisualList(p, b)); } else if (ch > 66) { b = Brushes.Red; vl.Add(new VisualList(p, b)); } else { b = Brushes.Yellow; vl.Add(new VisualList(p, b)); } } } }
И пытаюсь ее отрисовать с помощью DrawingVisual:
private void Print() { visual = new DrawingVisual(); using (DrawingContext dc = visual.RenderOpen()) { for (int i = 0; i < vl.Count; i++) { VisualList vlist = vl[i]; Brush brush = Brushes.Black; dc.DrawRectangle(vlist.Brushd, null, new Rect(vlist.Pointd, new Size(4, 4))); } } this.Dispatcher.BeginInvoke((Action)(() => { drawingSurface.AddVisual(visual); })); }
В итоге получаю ошибку: Необработанное исключение типа "System.Reflection.TargetInvocationException" в mscorlib.dll
Дополнительные сведения: Адресат вызова создал исключение. Как из фонового потока рисовать на форме?
Полный код
using System; using System.Collections.Generic; using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Shapes;
namespace matrix { ///

/// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { const int mh = 200; const int mw = 100; bool Stop = true; DrawingVisual visual; List vl = new List();
public MainWindow() { InitializeComponent(); }
private void TestWindow_Loaded(object sender, RoutedEventArgs e) { Thread trMatrix = new Thread(Draw); trMatrix.SetApartmentState(ApartmentState.STA); trMatrix.Start(); }
private void Draw() { while (Stop) { Step(); Print(); }
}
private void Print() { visual = new DrawingVisual(); using (DrawingContext dc = visual.RenderOpen()) { for (int i = 0; i < vl.Count; i++) { VisualList vlist = vl[i]; Brush brush = Brushes.Black; dc.DrawRectangle(vlist.Brushd, null, new Rect(vlist.Pointd, new Size(4, 4))); } } this.Dispatcher.BeginInvoke((Action)(() => { drawingSurface.AddVisual(visual); })); }
public void Step() { Point p; Brush b; Random r = new Random();
for (int i = 0; i < mh; i++) { for (int j = 0; j < mw; j++) { p = new Point(i*5, j*5); int ch = r.Next(0, 100); if (ch <= 33) { b = Brushes.Green; vl.Add(new VisualList(p, b)); } else if (ch > 66) { b = Brushes.Red; vl.Add(new VisualList(p, b)); } else { b = Brushes.Yellow; vl.Add(new VisualList(p, b)); } } } } }
public class VisualList { public VisualList(Point pointd, Brush brushd) { Pointd = pointd; Brushd = brushd; }
public Point Pointd { get; set; } public Brush Brushd { get; set; } } }
Код класса рисования
using System.Collections.Generic; using System.Windows.Controls; using System.Windows.Media;
namespace TestDifferentWpf { class DrawingClass : Canvas { private List visuals = new List(); protected override int VisualChildrenCount { get { return visuals.Count; } }
protected override Visual GetVisualChild(int index) { return visuals[index]; }
public void AddVisual(Visual visual) { visuals.Add(visual); base.AddVisualChild(visual); base.AddLogicalChild(visual); }
public void DeleteVisual(Visual visual) { visuals.Remove(visual); base.RemoveVisualChild(visual); base.RemoveLogicalChild(visual); } } }
XAML


Ответ

Нет, так, как вы хотите, нельзя: все FrameworkElement'ы, которые добавляются друг в друга как Child'ы, должны принадлежать одному потоку.
Поэтому так просто рисовать из фонового потока не получится.
Обычно никто не заморачивается и рисует в главном потоке. Но если очень хочется, вам придётся освоить PresentationSource и VisualTarget
PresentationSource — это штука, позволяющая вставить в визуальное дерево какую-то совершенно чужую вещь. А VisualTarget позволяет соединять визуальные поддеревья, бегущие в разных потоках.

Вот примерная имплементация, которая производит рендеринг в фоновом потоке. Она сделана по этим источникам:
https://blogs.msdn.microsoft.com/dwayneneed/2007/04/26/multithreaded-ui-hostvisual/ http://gettinggui.com/creating-a-busy-indicator-in-a-separate-thread-in-wpf/
Итак, для начала, заводим нашу имплементацию PresentationSource
// https://blogs.msdn.microsoft.com/dwayneneed/2007/04/26/multithreaded-ui-hostvisual/ // https://github.com/higankanshi/Meta.Vlc/blob/master/Meta.Vlc.Wpf // /VisualTargetPresentationSource.cs public class VisualTargetPresentationSource : PresentationSource, IDisposable { public VisualTargetPresentationSource(HostVisual hostVisual) { _visualTarget = new VisualTarget(hostVisual); AddSource(); }
public override Visual RootVisual { get => _visualTarget.RootVisual; set { Visual oldRoot = _visualTarget.RootVisual; _visualTarget.RootVisual = value; RootChanged(oldRoot, value);
if (value is UIElement rootElement) { rootElement.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); rootElement.Arrange(new Rect(rootElement.DesiredSize)); } } }
protected override CompositionTarget GetCompositionTargetCore() => _visualTarget; public override bool IsDisposed => _isDisposed;
public void Dispose() { RemoveSource(); _isDisposed = true; }
private VisualTarget _visualTarget; private bool _isDisposed; }
Остальную функциональность я упаковал в MainWindow, но её, вероятно, стоит разбить на вспомогательные классы.
Объяснение по коду. В конструкторе создаётся HostVisual, на который «наденется» VisualTarget через VisualTargetPresentationSource, и добавляется в визуальное дерево. Поскольку стандартные контролы не умеют добавлять Visual'ы, мы пользуемся DrawingClass из вопроса.
Далее, мы создаём STA-поток, в котором и будет происходить рендеринг поддерева, и запускаем его.
В потоке мы создаём VisualTargetPresentationSource. Затем, нам нужно сначала создать диспетчер, а потом выполнить на нём код, для этого используется трюк с InvokeAsync. (Dispatcher.Run() — блокирующая функция!)
В коде мы создаём Random (один раз, а не на каждой итерации), и в цикле вызываем функции Step и Draw из вопроса. Я немного переписал функции, чтобы они работали не с полями, а с параметрами. Ну и между итерациями я вставил Task.Delay, чтобы не гонять вечный холостой цикл.
Вот весь код:
public partial class MainWindow : Window { public MainWindow() { InitializeComponent();
var hv = new HostVisual(); drawingSurface.AddVisual(hv); Thread trMatrix = new Thread(() => Draw(hv)) { IsBackground = true }; trMatrix.SetApartmentState(ApartmentState.STA); trMatrix.Start(); }
void Draw(HostVisual outerhv) { VisualTargetPresentationSource vtps = new VisualTargetPresentationSource(outerhv); var dispatcher = Dispatcher.CurrentDispatcher; dispatcher.InvokeAsync(async () => { Random r = new Random(); while (true) { var vl = Step(r); var visual = Print(vl); vtps.RootVisual = visual; await Task.Delay(50); } }); Dispatcher.Run(); vtps.Dispose(); }
public List Step(Random r) { const int mh = 200; const int mw = 100;
List vl = new List();
for (int i = 0; i < mh; i++) { for (int j = 0; j < mw; j++) { Point p = new Point(i * 5, j * 5); int ch = r.Next(0, 3); Brush b = ch == 0 ? Brushes.Green : ch == 1 ? Brushes.Yellow : Brushes.Red; vl.Add(new VisualList(p, b)); } }
return vl; }
private Visual Print(List vl) { var visual = new DrawingVisual(); using (DrawingContext dc = visual.RenderOpen()) { for (int i = 0; i < vl.Count; i++) { VisualList vlist = vl[i]; Brush brush = Brushes.Black; dc.DrawRectangle(vlist.Brushd, null, new Rect(vlist.Pointd, new Size(4, 4))); } }
return visual; } }
Получилось вот что:


На старой системе пользоваться async/await может быть сложно, вместо этого приходится использовать таймер:
public void Draw(HostVisual outerhv) { VisualTargetPresentationSource vtps = new VisualTargetPresentationSource(outerhv); var dispatcher = Dispatcher.CurrentDispatcher; DispatcherTimer dt = new DispatcherTimer(DispatcherPriority.Normal, dispatcher) { Interval = TimeSpan.FromMilliseconds(50), IsEnabled = true }; Random r = new Random(); dt.Tick += (o, args) => { var vl = Step(r); var visual = Print(vl); vtps.RootVisual = visual; }; Dispatcher.Run(); vtps.Dispose(); }

многократный вывод ошибки в консоль (пишу змейку помогите js'еры)

index.js:182 Uncaught TypeError: document.querySelector(...).keydown is not a function at index.js:182
Uncaught TypeError: Cannot read property '0' of undefined at Snake.move (index.js:82) at setInterval (index.js:171)
const random = (max) => (Math.random() * (max + 1)) | 0; let c = document.getElementById('c'); let ctx = c.getContext('2d'); let width = c.width; let height = c.height; let blockSize = 10; let widthInBlocks = width / blockSize; let heightInBlocks = height / blockSize; let score = 0; let drawBorder = () => { ctx.fillStyle = 'Gray'; ctx.fillRect(0, 0, width, bBorderlockSize); ctx.fillRect(0, height - blockSize, width, blockSize); ctx.fillRect(width - blockSize, 0, blockSize, height); }; let drawScore = () => { ctx.font = '20px Courier'; ctx.fillStyle = 'Black'; ctx.textAlign = 'left'; ctx.textBaseline = 'top'; ctx.fillText('Счет: ' + score, blockSize, blockSize); }; let gameOver = () => { clearInterval(intervalId); ctx.font = '60px Courier'; ctx.fillStyle = 'Black'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText('Конец игры: ', width / 2, height / 2); }; let circle = (x, y, radius, fillCircle) => { ctx.beginPath(); ctx.arc(x, y, radius, 0, Math.PI * 2, false); if (fillCircle) { ctx.fill(); } else { ctx.stroke(); } }; let Block = function(col, row) { this.col = col; this.row = row; }; Block.prototype.drawSquare = (color) => { let x = this.col * blockSize; let y = this.row * blockSize; ctx.fillStyle = color; ctx.fillRect(x, y, blockSize, blockSize); }; Block.prototype.drawCircle = (color) => { let centerX = this.col * blockSize + blockSize / 2; let centerY = this.row * blockSIze + blockSize / 2; ctx.fillStyle = color; circle(centerX, centerY, blockSize / 2, true); }; Block.prototype.equal = (otherBlock) => { return this.col === otherBlock.col && this.row === otherBlock.row; }; let Snake = function() { this.segments = [ new Block(7, 5), new Block(6, 5), new Block(5, 5) ]; this.direction = 'right'; this.nextDirection = 'right'; }; Snake.prototype.draw = () => { for (let i = 0; i < this.segments.length; i++) { this.segments[i].drawSquare('Blue'); } }; Snake.prototype.move = () => { let head = this.segments[0]; let newHead; this.direction = this.nextDirection; switch (this.direction) { case 'right': newHead = new Block(head.col + 1, head.row); break; case 'down': newHead = new Block(head.col, head.row + 1); break; case 'left': newHead = new Block(head.col - 1, head.row); break; case 'up': newHead = new Block(head.col, head.row - 1); break; }; if (this.checkCollision(newHead)) { gameOver(); return; } this.segments.unshift(newHead); if (newHead.equal(apple.position)) { score++; apple.move(); } else { this.segments.pop() } }; Snake.prototype.checkCollision = (head) => { let leftCollusion = (head.col === 0); let topCollusion = (head.row === 0); let rightCollusion = (head.col === widthInBlocks - 1); let bottomCollusion = (head.col === heightInBlocks - 1); let wallCollusion = leftCollusion || topCollusion || rightCollusion || bottomCollusion; let selfCollusion = false; for (let i = 0; i < this.segments.length; i++) { if (head.equal(this.segments[i])) { selfCollusion = true; } } return wallCollusion || selfCollusion; }; Snake.prototype.setDirection = (newDirection) => { if (this.direction === 'up' && newDirection === 'down') { return; } else if (this.direction === 'right' && newDirection === 'left') { return; } else if (this.direction === 'down' && newDirection === 'up') { return; } else if (this.direction === 'left' && newDirection === 'right') { return; } this.nextDirection = newDirection; }; let Apple = function() { this.position = new Block(10, 10); }; Apple.prototype.draw = () => { this.position.drawCircle('LimeGreen'); }; Apple.prototype.move = () => { let randomCol = Math.floor(random(widthInBlocks)) + 1; let randomRow = Math.floor(random(heightInBlocks)) + 1; this.position = new Block(randomCol, randomRow); }; let snake = new Snake; let apple = new Apple; let intervalId = setInterval(() => { ctx.clearRect(0, 0, width, height); drawScore(); snake.move(); snake.draw(); apple.draw(); drawBorder(); }, 100); let directions = { 37: 'left', 38: 'up', 39: 'right', 40: 'down' }; document.querySelector('body').keydown((event) => { let newDirection = directions[event.keyCode]; if (newDirection !== undefined) { snake.setDirection(newDirection); } }); #canvas { width: 400px; height: 400px; }


Ответ

Что касается первой ошибки:
document.querySelector('body').keydown((event) => {
keydown - это НЕ функция. Возможно тут сказалось влияние jQuery, в котором подписка на событие действительно выглядит так.
Для решения можно использовать метод addEventListener
document.querySelector('body').addEventListener('keydown',e => {...})

Что касается второй ошибки.
Проблема в чрезмерном увлечении стрелочными функциями.
this для стрелочных функций определяется в момент их создания (подробнее в вопросе Потеря контекста вызова)
В данном случае в момент создания, this ссылается на глобальный объект window, а не на ожидаемый объект sneak
Решение обычное - использование в этих случаях обычных функций, а не стрелочных.

Почему нельзя использовать NEWID() в функциях?

Собственно вопрос, почему его нельзя использовать в функциях и группу других похож недетерминированных функций(Например, Rand())?
Это какая-то особенность MS SQL или и в других СУБД похожая ситуация?
Со стороны я не вижу причин запрета.


Ответ

Способ обхода:
create view getNewID as select newid() as new_id
create function myfunction () returns uniqueidentifier as begin return (select new_id from getNewID) end
Почему - возможно NEWID() изменяет состояние БД:
User-defined functions cannot be used to perform actions that modify the database state.

Угол отображения 3d графиков

Графики выглядят как изометрическая проекция, что не очень удобно для оценки того, что происходит по оси delay. Для сравнения "на глаз" было бы хорошо, чтобы ось delay находилась параллельно плоскости монитора, а accum periods перпендикулярно. Как прописать в коде угол, под которым отображаются графики?

x = np.arange (0, 64, 1) y = np.arange (0, aver, 1) xgrid, ygrid = np.meshgrid(x, y) zgrid = ifft_data x, y, z = xgrid,ygrid,zgrid fig = pylab.figure() axes = Axes3D(fig) axes.plot_surface(x, y, z) plt.xlabel('delay') plt.ylabel('accumulation periods') pylab.show()


Ответ

Воспользуйтесь ax.view_init(ax.elev, ax.azim)
Пример:
from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt from matplotlib import cm import numpy as np
fig = plt.figure() ax = fig.gca(projection='3d')
# Make data. X = np.arange(-5, 5, 0.25) Y = np.arange(-5, 5, 0.25) X, Y = np.meshgrid(X, Y) R = np.sqrt(X**2 + Y**2) Z = np.sin(R) surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm, linewidth=0, antialiased=False)
Результат (по умолчанию):

После поворота:
ax.view_init(30, -89)

PS чтобы найти какие вам нужны значения углов - легче всего начертить график с углами по умолчанию в Jupyter (iPython), повернуть график мышкой так как вам надо и посмотреть какие углы получились:
In [209]: print('elev:\t{}\t\tazim:\t{}'.format(ax.elev, ax.azim)) elev: 30 azim: -89

Отслеживание появления нового процесса Windows

Добрый день. Надо отследить появление новых процессов. Есть ли в Windows слот, на который поступает сигнал при появлении нового процесса? Иначе как это можно реализовать? В psapi подобного не нашёл. Есть предположение через определённые интервалы времени сверять список PID, но надеюсь найти более простое решение.


Ответ

Можно сделать трейсинг через системную функцию ZwQuerySystemInformation. Внимание! Microsoft не рекомендует, начиная с Windows 8, её использовать, предлагая замену, но, как проверено только что на Windows 10, она работает.
Пример реализации и использования привожу на Delphi, в виде консольного приложения. Поскольку речь касается функций WinAPI, переписать на C/C++ - легко.
program ListOfProcess;
{$APPTYPE CONSOLE}
uses SysUtils, windows, System.Generics.Collections;
// поскольку подход писался очень давно (во времена Windows 2000), // типы и константы определены, поскольку в то время их ещё не было в // системных модулях Delphi. Хотя и сейчас, возможно, некоторых нет.
type NTStatus = cardinal; PVOID = pointer; USHORT = WORD; UCHAR = byte; PWSTR = PWideChar;
const
STATUS_SUCCESS = NTStatus($00000000); STATUS_ACCESS_DENIED = NTStatus($C0000022); STATUS_INFO_LENGTH_MISMATCH = NTStatus($C0000004);
const SystemProcessesAndThreadsInformation = 5;
type PClientID = ^TClientID; TClientID = packed record
UniqueProcess:cardinal; UniqueThread:cardinal; end;
PUnicodeString = ^TUnicodeString; TUnicodeString = packed record Length: Word; MaximumLength: Word; Buffer: PWideChar; end;
PVM_COUNTERS = ^VM_COUNTERS; VM_COUNTERS = packed record PeakVirtualSize, VirtualSize, PageFaultCount, PeakWorkingSetSize, WorkingSetSize, QuotaPeakPagedPoolUsage, QuotaPagedPoolUsage, QuotaPeakNonPagedPoolUsage, QuotaNonPagedPoolUsage, PagefileUsage, PeakPagefileUsage: dword; end;
PIO_COUNTERS = ^IO_COUNTERS; IO_COUNTERS = packed record
ReadOperationCount, WriteOperationCount, OtherOperationCount, ReadTransferCount, WriteTransferCount, OtherTransferCount: LARGE_INTEGER; end;
PSYSTEM_THREADS = ^SYSTEM_THREADS; SYSTEM_THREADS = packed record KernelTime, UserTime, CreateTime: LARGE_INTEGER; WaitTime: dword; StartAddress: pointer; ClientId: TClientId; Priority, BasePriority, ContextSwitchCount: dword; State: dword; WaitReason: dword; end;
PSYSTEM_PROCESSES = ^SYSTEM_PROCESSES; SYSTEM_PROCESSES = packed record NextEntryDelta, ThreadCount: dword; Reserved1 : array [0..5] of dword; CreateTime, UserTime, KernelTime: LARGE_INTEGER; ProcessName: TUnicodeString; BasePriority: dword; ProcessId, InheritedFromProcessId, HandleCount: dword; Reserved2: array [0..1] of dword; VmCounters: VM_COUNTERS; IoCounters: IO_COUNTERS;
Threads: array [0..0] of SYSTEM_THREADS; end;
// основная функция, которую мы будем использовать
Function ZwQuerySystemInformation(ASystemInformationClass: dword; ASystemInformation: Pointer; ASystemInformationLength: dword; AReturnLength:PCardinal): NTStatus; stdcall;external 'ntdll.dll';
// Функция получения буфера с системной информацией Function GetInfoTable(ATableType:dword):Pointer; var mSize: dword; mPtr: pointer; St: NTStatus; begin Result := nil; mSize := $4000; //начальный размер буфера
repeat // подгонка размера буфера mPtr := VirtualAlloc(nil, mSize, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE); if mPtr = nil then Exit; St := ZwQuerySystemInformation(ATableType, mPtr, mSize, nil); if St = STATUS_INFO_LENGTH_MISMATCH then
begin VirtualFree(mPtr, 0, MEM_RELEASE); mSize := mSize * 2; end; until St <> STATUS_INFO_LENGTH_MISMATCH; if St = STATUS_SUCCESS then Result := mPtr else VirtualFree(mPtr, 0, MEM_RELEASE);
end; // приведу пример использовании фунции: var info, info2: PSystem_Processes; i, j, k: integer; t, t1: LARGE_INTEGER; process_id:TDictionary; // здесь будем хранить информацию begin process_id := TDictionary.Create;
// Список процессов на момент старта программы info := GetInfoTable(SystemProcessesAndThreadsInformation); info2 := info;
while (info2^.NextEntryDelta <> 0) do
begin if not process_id.ContainsKey(info2^.ProcessId) then process_id.Add(info2^.ProcessId, info2^); info2 := Pointer(dword(info2)+info2^.NextEntryDelta); end;
VirtualFree(info, 0, MEM_RELEASE);
while true do // нужно вставить вариант выхода из цикла. Разумеется, Ctrl+C всегда сработает :) begin Sleep(2000); // будем проверять наличие новых процессов каждые 2 секунды info := GetInfoTable(SystemProcessesAndThreadsInformation); info2 := info;
while (info2^.NextEntryDelta <> 0) do
begin if not process_id.ContainsKey(info2^.ProcessId) then begin writeln(info2^.ProcessId, ' - появился'); process_id.Add(info2^.ProcessId,info2^); // если будем постоянно добавлять, словарь разрастётся, // надо бы подумать и об удалении элементов, оставляю ТС :) end; info2 := Pointer(dword(info2)+info2^.NextEntryDelta); end; VirtualFree(info, 0, MEM_RELEASE); end; process_id.Free; end.

Canvas (Круг) низкого разрешения. Android Studio

Для рисования квадрата использую замену ImageView на нарисованный Круг (Rectangle)Вот мой код для создания ImageView и рисования круга:
imageView = new ImageView(getApplicationContext()); imageView.setId(R.id.imageViewCircle); imageView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT)); ((RelativeLayout)swipe).addView(imageView); ImageView imageView=(ImageView) findViewById(R.id.imageViewCircle);
bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); canvas = new Canvas(bitmap); paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(Color.BLACK); canvas.drawCircle(50, 50, 40, paint);
imageView.setImageBitmap(bitmap);
Вот что у меня выходит: (Посмотрите Скриншот)


Ответ

Похоже ImageView масштабирует вашу маленькую картинку на весь экран.
Попробуйте установить imageView.setScaleType(ImageView.ScaleType.CENTER)

Java. Доступ к полю родительского класса из метода внутреннего класса

Вопрос не несет практической значимости, но очень интересен в плане понимания языка.
public class A { private class B {} private String myFinalNameField;
private B b = new B() { private void myMethod(String myFinalNameFields) { [???]myFinalNameFields = myFinalNameFields; } }; }
Как присвоить полю myFinalNameField класса А значение параметра myFinalNameFields метода myMethod класса B ? Скорее всего я неверно сформулировал вопрос, это можно сделать, добавив например префикс:
public class A { private class B {} private String prefixMyFinalNameField;
private B b = new B() { private void myMethod(String myFinalNameFields) { prefixMyFinalNameField = myFinalNameFields; } };
Есть ли возможность обратиться к приватному не статичному полю внешнего класса, что то вроде как this или super. Т.е. иметь абсолютно идентичные имена полей, но различать какая переменная к какому классу относится, точнее выполнить присвоение.


Ответ

Если я правильно понял суть вопроса, то к этой переменной вы можете обратиться следующим образом:
A.this.myFinalNameFields = myFinalNameFields;
Немного поясню:
class A {
private class B {}
private String myFinalNameFields;
private B b = new B() {
private String myFinalNameFields;
private void myMethod(String myFinalNameFields) { A.this.myFinalNameFields = myFinalNameFields; //Присвоит значение полю класса A this.myFinalNameFields = myFinalNameFields; //Присвоит значение полю класса B } }; }

Как подключать шрифты при сборке scss на webpack?

Пользуясь гайдами, пытаюсь собрать все свои стили в одну сборку на Webpack. Имеется главный файл, в него импортируется другой, в котором несколько правил @font-face с путями к файлам шрифтов. При сборке Webpack выдаёт ошибку по этим путям, говорит: нужен специальный загрузчик:
ERROR in ./fonts/a_coppergothcaps-bold.ttf Module parse failed: Unexpected character ' ' (1:0) You may need an appropriate loader to handle this file type. (Source code omitted for this binary file)
Но мне не то чтобы нужно (или нужно?) добавлять эти файлы в сборку. Мне достаточно, если в сборке останутся эти правила, и браузер сам подключит шрифты по ссылкам в них. Как сказать Webpack, чтобы не пытался обрабатывать эти пути, но просто вставлял их, как есть? Или я неправильно вижу решение проблемы? Может, я шрифтами неправильно распоряжаюсь?
Вот такие правила в конфиге:
module: { rules: [ { test: /\.scss$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader', 'sass-loader'] }) } ] },


Ответ

Ссылка на полный конфиг
Вот мой способ подключения шрифтов для SCSS:
{ test: /\.(eot|svg|ttf|woff|woff2)$/, use: [ { loader: 'file-loader?name=./assets/fonts/webfonts/[name].[ext]' }, { loader: 'file-loader?name=./assets/fonts/Roboto/[name].[ext]' } ] }

Что бы это заработало нужно установить file-loader
После этого нужно загрузить шрифты в SCSS:
@font-face { font-family: 'Roboto Black'; src: url("/fonts/Roboto/Roboto-Black.ttf"); }

Настройки webpack-dev-server:
devServer: { contentBase: [path.resolve(__dirname, "build"), path.resolve(__dirname, "assets")], compress: true, port: 4200, historyApiFallback: true, noInfo:true }

UPDATE 1
У меня описания шрифтов находятся в файле src/fonts.scss и файл src/variable.scss для хранения переменных размеров, цветов и т.п. В variable.scss импортируется fonts.scss -> @import "/fonts.scss"; и после этого в любом другом файле стилей можно импортировать variable.scss. В определении шрифтор должен указываться не относительный путь до файла, а url. Можно протестировать корректность вводимого адреса в браузере, например http://localhost:4200/fonts/Roboto/Roboto-Black.ttf, если было предложено сохранить файл значит все правильно.

Декартово произведение нескольких массивов

Как можно реализовать декартово произведение нескольких массивов в JavaScript?
// например cartesian([1,2], [10,20], [100,200,300]) // будет равно // [[1, 10, 100], [1, 10, 200], [1, 10, 300], [1, 20, 100], [1, 20, 200], ...]


Ответ

Самый короткий способ на чистом JavaScript
const f = (a, b) => [].concat(...a.map(ai => b.map(bi => ai.concat([bi])))); const cartesian = (...arrays) => arrays.reduce((a, b) => f(a, b), [[]]);
Используются
методы для массивов .map, .reduce, .concat оператор расширения ... и синтаксис оставшихся аргументов
То же самое в виде одной функции с комментариями
const cartesian = (...arrays) => // итеративно получаем декартово произведение // нескольких первых массивов из arrays, // начиная с нуля массивов и пустого декартова произведения --- [[]] arrays.reduce((cartesianPart, array) => // сглаживание массива массивов [].concat(... // cartesianPart --- декартово произведение нескольких первых массивов из arrays cartesianPart.map(cartesianPartTuple => // array --- новый массив из arrays для добавления в декартово произведение array.map(arrayElement => // cartesianPartTuple --- массив-префикс одного из элементов декартова произведения // arrayElement --- элемент одного из массива из arrays cartesianPartTuple.concat([arrayElement]) ) ) ), [[]] );
То же самое с использованием методов lodash
const cartesian = (...arrays) => _.reduce(arrays, (a, b) => _.flatten( _.map(a, ai => _.map(b, bi => ai.concat([bi]) ) ) ), [[]] );
Здесь методы JavaScript заменены на эквивалентные из lodash:
массив.map(маппер) ↔ _.map(массив, маппер) массив.reduce(редьюсер) ↔ _.reduce(массив, редьюсер) [].concat(...массив) ↔ _.flatten(массив)
Нерекурсивный способ с явным построением элемента декартова произведения по его номеру
function cartesian(...arrays) { // находим число элементов в декартовом произведении let resultLength = 1; for (let array of arrays) { resultLength *= array.length; }
// создаём массив такого размера и перебираем номер элемента let result = new Array(resultLength); for (let i = 0; i < resultLength; ++i) { // один элемент декартова произведения let element = new Array(arrays.length); let elementIndex = i; // цикл в обратном порядке нужен чтобы элементы начинали изменяться с конца for (let j = arrays.length - 1; j >= 0; --j) { const array = arrays[j]; // имеем биекцию между индексами элементов декартова произведения (числа от 0 до resultLength-1) // и кортежами длины arrays.length, в которых каждый элемент — индекс в соответствующем массиве element[j] = array[elementIndex % array.length]; // целочисленное деление elementIndex = Math.floor(elementIndex / array.length); } result[i] = element; } return result; }
Рекурсивный способ
С помощью рекурсии будут создаваться элементы декартова произведения: начиная с пустого массива на каждом шаге рекурсии перебираются все элементы текущего массива, создаётся копия набранного префикса элемента декартова произведения, к копии добавляется элемент массива и на полученном новом префиксе делается рекурсивный вызов.
function cartesian(...arrays) { let result = []; // функция, которая будет рекурсивно вызываться // глубина рекурсии равна arrays.length // в процессе рекурсии функция будет создавать часть элемента декартова произведения // в конце рекусрии функция добавит созданный элемент в массив result const recursion = (tuplePart) => { if (tuplePart.length === arrays.length) { result.push(tuplePart); } else { const array = arrays[tuplePart.length]; for (let element of array) { // создаём копию tuplePart и добавляем в неё очередной элемент const tuplePartWithNewElement = tuplePart.concat([element]); recursion(tuplePartWithNewElement); } } }; recursion([]); return result; }
Сниппет, в котором проверяется корректность работы всех предложенных способов
// cartesian 1 const f = (a, b) => [].concat(...a.map(ai => b.map(bi => ai.concat([bi])))); const cartesian1 = (...arrays) => arrays.reduce((a, b) => f(a, b), [[]]); // cartesian 2 const cartesian2 = (...arrays) => // итеративно получаем декартово произведение // нескольких первых массивов из arrays, // начиная с нуля массивов и пустого декартова произведения --- [[]] arrays.reduce((cartesianPart, array) => // сглаживание массива массивов [].concat(... // cartesianPart --- декартово произведение нескольких первых массивов из arrays cartesianPart.map(cartesianPartTuple => // array --- новый массив из arrays для добавления в декартово произведение array.map(arrayElement => // cartesianPartTuple --- массив-префикс одного из элементов декартова произведения // arrayElement --- элемент одного из массива из arrays cartesianPartTuple.concat([arrayElement]) ) ) ), [[]] ); // cartesian 3 const cartesian3 = (...arrays) => _.reduce(arrays, (a, b) => _.flatten( _.map(a, ai => _.map(b, bi => ai.concat([bi]) ) ) ), [[]] ); // cartesian 4 function cartesian4(...arrays) { // находим число элементов в декартовом произведении let resultLength = 1; for (let array of arrays) { resultLength *= array.length; } // создаём массив такого размера и перебираем номер элемента let result = new Array(resultLength); for (let i = 0; i < resultLength; ++i) { // один элемент декартова произведения let tuple = new Array(arrays.length); let tupleIndex = i; // цикл в обратном порядке нужен чтобы элементы начинали изменяться с конца for (let j = arrays.length - 1; j >= 0; --j) { const array = arrays[j]; // имеем биекцию между индексами элементов декартова произведения (числа от 0 до resultLength-1) // и кортежами длины arrays.length, в которых каждый элемент — индекс в соответствующем массиве tuple[j] = array[tupleIndex % array.length]; // целочисленное деление tupleIndex = Math.floor(tupleIndex / array.length); } result[i] = tuple; } return result; } // cartesian 5 function cartesian5(...arrays) { let result = []; // функция, которая будет рекурсивно вызываться // глубина рекурсии равна arrays.length // в процессе рекурсии функция будет создавать часть элемента декартова произведения // в конце рекусрии функция добавит созданный элемент в массив result const recursion = (tuplePart) => { if (tuplePart.length === arrays.length) { result.push(tuplePart); } else { const array = arrays[tuplePart.length]; for (let element of array) { // создаём копию tuplePart и добавляем в неё очередной элемент const tuplePartWithNewElement = tuplePart.concat([element]); recursion(tuplePartWithNewElement); } } }; recursion([]); return result; } // tests const cartesians = [ cartesian1, cartesian2, cartesian3, cartesian4, cartesian5 ]; const tests = [ { name: 'product of single array', input: [ [1, 2, 3] ], output: [ [1], [2], [3] ] }, { name: 'product of two arrays', input: [ [1, 2, 3], [10, 20] ], output: [ [1, 10], [1, 20], [2, 10], [2, 20], [3, 10], [3, 20] ] }, { name: 'product of three arrays', input: [ [1, 2], [10, 20], [100, 200, 300] ], output: [ [1, 10, 100], [1, 10, 200], [1, 10, 300], [1, 20, 100], [1, 20, 200], [1, 20, 300], [2, 10, 100], [2, 10, 200], [2, 10, 300], [2, 20, 100], [2, 20, 200], [2, 20, 300] ] }, { name: 'nested arrays', input: [ [[1], [2], [3]], [[10], [20]] ], output: [ [[1], [10]], [[1], [20]], [[2], [10]], [[2], [20]], [[3], [10]], [[3], [20]] ] } ]; console.log('если нет сообщений об ошибке, то все функции работают правильно'); cartesians.forEach((cartesian, index) => { for (let test of tests) { const output = cartesian(...test.input); const ok = _.isEqual(output, test.output); if (!ok) { console.log(`FAIL: cartesian function #${index + 1} for test ${test.name}`); console.log(` expected: ${JSON.stringify(test.output)}`); console.log(` received: ${JSON.stringify(output)}`); } } });
Замечание о пустом декартовом произведении
Практически все предложенные способы некорректно обрабатывают пустое декартово произведение, то есть вызов функции cartesian без аргументов. Декартово произведение нуля множеств равно пустому множеству, в нашем случае это пустой массив. При желании можно добавить проверку на это.
Готовые библиотечные реализации
В некоторых библиотеках существует функция декартова произведения:
js-combinatorics → cartesianProduct cartesian-product — npm, github d3-array → cross (только для двух массивов)

Взять следующий элемент ассоциативного массива на PHP

Добрый день, столкнулся с такой проблемой. Есть ассоциативный массив.
К примеру.
$foo = array('x'=>'x_val','y'=>'y_val','z'=>'z_val');
И есть цикл foreach
foreach ($foo as $key=>$val){ //Тут какая то логика }
Нужно взять в текущей итерации следующий $val. Ну или $key
Как можно этого добиться ?


Ответ

проще всего, будет использовать вспомогательный массив соответствий
$foo = array('x'=>'x_val', 'y'=>'y_val', 'z'=>'z_val');
$keys = array_keys($foo); array_shift($keys); $matches = array_combine(array_keys($foo), $keys + [-1 => null]);
foreach($foo as $k => $v){ $nextKey = $matches[$k]; print_r([$k, $nextKey]); }
результат
Array( [x] => y [y] => z [z] => )
Однако, вообще стоит задуматься, что есть порядок ключей в ассоциативном массиве, и имеет ли он в целом смысл и гарантирован ли при обходе

Сколько памяти занимают объекты?

Провел несколько тестов, и был весьма удивлен... Режим компиляции x64. Первый тест показал 4 байта, здесь все нормально. Второй 32. Ого подумал я. И трейтий 32 WTF ???
static int count = 10000000;
static void Array_C() { var size = GC.GetTotalMemory(true); var arr = new int[count];
for (var i = 0; i < count; ++i) { arr[i] = i; }
var mem = GC.GetTotalMemory(true) - size;
Console.WriteLine("Выделено памяти: " + mem + ", размер одного объекта: " + Math.Truncate((double)mem / count) + ", код последней " + arr.Last()); }
static void Array_E() { var size = GC.GetTotalMemory(true); var arr = new object[count];
for (var i = 0; i < count; ++i) { arr[i] = new object(); }
var mem = GC.GetTotalMemory(true) - size;
Console.WriteLine("Выделено памяти: " + mem + ", размер одного объекта: " + Math.Truncate((double)mem / count) + ", код последней " + arr.Last().GetHashCode()); }
static void Array_F() { var size = GC.GetTotalMemory(true); var arr = new C[count];
for (var i = 0; i < count; ++i) { arr[i] = new C { Val0 = i, Val1 = i }; }
var mem = GC.GetTotalMemory(false) - size;
Console.WriteLine("Выделено памяти: " + mem + ", размер одного объекта: " + Math.Truncate((double)mem / count) + ", код последней " + arr.Last().Val0 + arr.Last().Val1); }
[StructLayout(LayoutKind.Sequential, Pack = 1)] class C { public int Val0; public int Val1; }
Вопрос даже не в том почему во втором тесте один экземляр занимает 32 байта. А в том почему в третьем тесте экземпляр не занимает 40 байт.


Ответ

Во первых, в данном коде неправильно измеряется размер для массива ссылочных типов. Код:
var size = GC.GetTotalMemory(true); var arr = new object[count];
for (var i = 0; i < count; ++i) { arr[i] = new object(); }
var mem = GC.GetTotalMemory(true) - size;
Измеряет память под массив ссылок + память по объекты. Надо так:
var arr = new object[count]; var size = GC.GetTotalMemory(true);
for (var i = 0; i < count; ++i) { arr[i] = new object(); }
var mem = GC.GetTotalMemory(true) - size;
Во вторых, арифметика Размер C = Размер object + 2 * Размер int не работает: все несколько сложнее.
В CLR существует минимальный размер объекта, см. object.h
// // The generational GC requires that every object be at least 12 bytes // in size.
#define MIN_OBJECT_SIZE (2*sizeof(BYTE*) + sizeof(ObjHeader))
Для 64-разрядной версии минимальный размер 2 * 8 + 8 = 24. Размер типа, меньшего 24 байта, дополняется до 24.
(Определение ObjHeader здесь: https://github.com/dotnet/coreclr/blob/master/src/gc/env/gcenv.object.h) Размер служебного блока, добавляемого к любому ссылочному типу, равен 16 байт (для x86 - 8 байт, см. например здесь, для x64 в два раза больше). Кроме того, предположительно, работает дополнение размера до числа, кратного 8.
Таким образом:
Размер объекта с 1 int полем = 24 байта Размер объекта с 2 int полями = 24 байта Размер объекта с 3 int полями = 32 байта

Не отображается текст виджета QLineEdit с задержкой time.sleep

Пользователь вводит букву в поле виджета QLineEdit, затем через секунду поле должно очиститься. Пауза работает, но текст не появляется. Как это сделать можно?
import sys, time from PyQt5.QtWidgets import QApplication, QWidget, QLineEdit, QVBoxLayout
class MyWindow(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.qle = QLineEdit() self.qle.textEdited.connect(self.method)
self.vbox = QVBoxLayout() self.vbox.addWidget(self.qle) self.setLayout(self.vbox)
def method(self): time.sleep(2) self.qle.clear()
if __name__ == "__main__": app = QApplication(sys.argv) window = MyWindow() window.resize(300, 70) window.show() sys.exit(app.exec_())


Ответ

Когда вы используете петлю обработки событий QApplication, не стоит пользоваться питоновским\системным sleep. В Qt есть для этого QTimer. В данном случае можно использовать статический метод singleShot. Он принимает параметры задержки в мс и слот-обработчик.
import sys from PyQt5.QtWidgets import QApplication, QWidget, QLineEdit, QVBoxLayout from PyQt5.QtCore import QTimer
class MyWindow(QWidget): def __init__(self): super().__init__() qle = QLineEdit() qle.textEdited.connect(lambda: QTimer.singleShot(2000, qle.clear))
vbox = QVBoxLayout() vbox.addWidget(qle) self.setLayout(vbox)
if __name__ == "__main__": app = QApplication(sys.argv) window = MyWindow() window.resize(300, 70) window.show() sys.exit(app.exec_())
В вашем же случае получалось, что time.sleep блокировал поток выполнения (поэтому текст не появлялся), через 2 секунды управление возвращалось приложению, происходила очистка текстового поля виджета, перерисовка окна.

Как назначить цену приложению в Google Play Console?

Как назначить цену приложению в Google Play Console?


Ответ

При заливке приложения не забыть сразу указать, что оно Платное. Иначе Бесплатное потом невозможно будет перевести в Платное - так задумано! ) Зайти в Настройки своего акаунта Зайти в Шаблоны цен Создать Новый шаблон цен Вернуться в приложение. Зайти в Настройки страницы приложения > Цены и Распространение и назначить нужный шаблон своему приложению
Рис. к пункту 2:
Рис. к пунктам 3,4:

Как разбить объект на части?

Есть объект типа - const lol = { z: 3, a: 4, b: 1, c: 6}
Как из него получить массив объектов типа - qwe = [{z: 3},{a: 4},{b: 1},{c: 6}]


Ответ

Функциональное решение, используются:
Object.entries метод .map для массивов Вычисление имён свойств в записи объекта Синтаксис () => ({ключ: значение}) для возврата объекта из лямбды
const object = { z: 3, a: 4, b: 1, c: 6}; const result = Object .entries(object) .map(entry => ({[entry[0]]: entry[1]})); console.log(result);

Почему sql server требует значение null?

Есть такой код -
CREATE TABLE [dbo].[Сотрудники] ( [Id] INT IDENTITY (1, 1) NOT NULL, [Имя] NCHAR (50) NOT NULL, [Фамлия] NCHAR (50) NOT NULL, [Отчество] NCHAR (50) NULL, [Дата рождения] DATE NOT NULL, [Должность] INT NOT NULL, [Отдел] INT NOT NULL, [Кабинет] INT NOT NULL, [Контакты] INT NOT NULL, [Город] NCHAR (50) NULL, [Адрес] NCHAR(100) NULL, [Телефон] NCHAR(10) NULL, PRIMARY KEY CLUSTERED ([Id] ASC));
Если я поставлю в Город, адрес или телефон not null, то при обновлении будет ошибка -
Warnings The column Адрес on table [dbo].[Сотрудники] must be changed from NULL to NOT NULL. If the table contains data, the ALTER script may not work. To avoid this issue, you must add values to this column for all rows or mark it as allowing NULL values, or enable the generation of smart-defaults as a deployment option
Почему так? Почему имя или фамилия могут быть notNull, а последнее три столбца нет?


Ответ

Потому что у вас в существующей таблице уже есть значения город, адрес или телефон с NULL.
Вам нужно сначала проапдейтить эти записи, а потом уже делать Alter table.
В общем-то вам об этом прямым текстом написано в сообщении об ошибке.

События отрабатывают самостоятельно WPF

В общем, столкнулся я с NullReferenceException и, в результате (длительной) отладки, обнаружил, что обработчик событий ComboBox.SelectionChanged вызывает метод-обработчик при старте приложения. Разметка ComboBox:

По идее такого не должно быть, или я ошибаюсь? Если нужны какие-то части программного кода, пишите, отвечу.


Ответ

По умолчанию ни один элемент не выделен. При этом SelectedIndex равен -1
Если вы меняете его на 0, то, разумеется, вызовется обработчик — вы ведь сами это попросили!
Если это нежелательно, можно сделать, например, следующее:
Вы можете завести булев флаг, и взвести его в конструкторе, после InitializeComponent (этот метод считывает и интерпретирует XAML). Флаг можно проверить в обработчике. Вы можете подписаться на изменения в code-behind вручную, после InitializeComponent Вы можете проанализировать в обработчике предыдущее состояние выделенного элемента, заглянув в SelectionChangedEventArgs Вы можете сделать код обработчика более общим, чтобы он не падал, будучи вызванным в момент, когда ни один элемент не отмечен.
Я бы порекомендовал попробовать последний вариант.

Завершение MediaPlayer при возврате аппаратной кнопкой “Назад”

У меня в приложении реализовано воспроизведение звука при просмотре слайдов. Когда я меняю слайд или кнопкой "Домой" выхожу из activity, сделано завершение медиаплеера. Однако если выхожу из просмотра слайда аппаратной кнопкой "Назад" телефона/планшета - MediaPlayer остается работать в фоновом режиме, что не соответствует логике работы приложения. Подскажите, как "прикрутить" остановку MediaPlayer к нажатию аппаратной кнопки "Назад"?
public class SliderActivity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener { static final String TAG = "myLogs"; ViewPager viewPager; CustomSwipeAdapter adapter; ToggleButton toggleButton; ImageButton imageButton;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); setContentView(R.layout.activity_slider); imageButton = (ImageButton) findViewById(R.id.imageButtonHome); View.OnClickListener clickHome = new View.OnClickListener() { @Override public void onClick(View v) { if(mp !=null && mp.isPlaying()){ mp.stop(); } GoHome(); } };
imageButton.setOnClickListener(clickHome); /* * Читаем json и создаем из него объект книги bookFiles */ Gson gson = new Gson(); int bookId = GetBookId(); String fileName = "book_" + bookId + ".json"; String gsResult = MyJSON.getData(getApplicationContext(), fileName); BookFiles bookFiles = gson.fromJson(gsResult, BookFiles.class);
final String folderB = "bookfiles_" + bookId; /* Получаем из объекта bookFiles массивы путей к файлам книги */ ArrayList pagesFiles = bookFiles.getPagesPath(); final ArrayList soundsFiles = bookFiles.getSoundsPath();
viewPager = (ViewPager) findViewById(R.id.view_pager); viewPager.setPageTransformer(true, new ZoomOutPageTransformer()); adapter = new CustomSwipeAdapter(this, pagesFiles); viewPager.setAdapter(adapter); toggleButton = (ToggleButton) findViewById(R.id.imageButtonPlay);
//слушаем номер слайда при перелистывании viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { Boolean first = true; @Override public void onPageScrolled(final int position, float positionOffset, int positionOffsetPixels) { if (first && positionOffset == 0 && positionOffsetPixels == 0){ onPageSelected(0); first = false; } mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { int pagen = position+1; @Override public void onCompletion(MediaPlayer mp) { viewPager.setCurrentItem(pagen, true); } });
}
@Override public void onPageSelected(int position) { String nameS = Uri.parse(soundsFiles.get(position)).getLastPathSegment(); if(mp != null){ mp.stop(); } getMedia(nameS, folderB); toggleButton.setOnCheckedChangeListener(SliderActivity.this);
if (toggleButton.isChecked()){ mp.start();
} }
@Override public void onPageScrollStateChanged(int state) {
} });
}
public int GetBookId() { Intent intent = getIntent(); int bookId = intent.getIntExtra("bookId", 1); return bookId; }
@Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) mp.start(); else if (mp.isPlaying()) { mp.pause(); }
}
public void getMedia(String nameS, String folderB) { try { final String soundPath = String.valueOf(getApplicationContext().getExternalFilesDir(folderB)); final Uri souF = Uri.fromFile(new File(soundPath, nameS)); final MediaPlayer mp = MyPlayer.getMp(getApplicationContext(), souF); mp.setAudioStreamType(AudioManager.STREAM_MUSIC); } catch (Exception e) { e.printStackTrace(); } }
private void GoHome() {
new Handler().postDelayed(new Runnable() { @Override public void run() { Intent intent = new Intent(SliderActivity.this, MainActivity.class); startActivity(intent); finish(); } }, 10); }
}


Ответ

Попробуйте так
@Override public void onBackPressed(){ super.onBackPressed(); if(mp!=null && mp.isPlaying()){ mp.release(); } }

Что делает std::remove_reference_t?

Применяю std::remove_reference_t для выделения памяти под тип указателя, т.е.:
p = new remove_reference_t [10];
Этот способ мне подсказали, но я не разобрался как работает remove_reference_t. Есть ли какие-то "подводные камни" о которых мне следовало бы знать?


Ответ

Если p имеет обычный "голый" указательный тип, то никаких подводных камней тут нет.
Особенность тут скорее содержится в decltype. Когда decltype применено непосредственно к имени переменной (напр. decltype(p)), то в результате получается тот тип, с которым эта переменная объявлена. А вот когда decltype применено к какому-то более сложному выражению, результирующий тип зависит от категории значения (value category) этого выражения. Для lvalue аргумента типа T получится ссылочный тип T &, т.е. lvalue-ссылка.
В этом случае *p - как раз lvalue. Ссылочный тип в new нас не устраивает, т.е. нам надо превратить тип T & обратно в T, по каковой причине и приходится применять std::remove_reference_t.

Как получить список изменённых файлов?

Можно ли получить список изменённых файлов в диапазоне определённых коммитов? т.е. нужно получить изменённые файлы после того, как был сделан пуш этих файлов, чтобы можно было указать, с какого по какой пуш выбрать файлы


Ответ

Получить голый список файлов:
git diff --name-only hash1 hash2
В каком коммите, что менялось:
git show --oneline --name-only hash1..hash2
Будьте внимательны, в списке будут присутствовать все затронутые файлы, включая удалённые. Если интересует, что именно произошло с файлами, смените ключ --name-only на --name-status

Запуск события на определенном блоке при скролле с использованием malihu custom scrollbar

В продолжение вопроса
Использую плагин malihu custom scrollbar
Есть такая простейшая структура:
$(window).load(function(){ var container = $('#container'); container.mCustomScrollbar({ axis:"x", theme:"dark-3", // scrollbarPosition: 'outside', advanced:{ autoExpandHorizontalScroll:true }, autoScrollOnFocus: true, callbacks:{ whileScrolling:function(){ var windowWidth = $(window).width(), thisLeft, thisWidth; $('section').each(function(){ thisLeft = $(this).offset().left; thisWidth = $(this).width(); if(thisLeft < windowWidth ){ console.log($(this).attr('id')); }else{ } }); } } }); }); main { display: flex; flex-flow: row nowrap; align-items: center; align-content: center; justify-content: space-between; } section { display: block; width: 500px; border: 1px solid #000; padding: 1rem; margin-bottom: 2rem; } .js-page-scroll { width: 100%; overflow-x: auto; }

1

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

2

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

3

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

4

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

5

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?


Суть проблемы в том, что при доскролле до секции должен выводится ее номер (в консоле) единожды, т.е при обратном скролле ничего в консоле не выводить.
Конкретная задача с реализацией TweenMax:
$(window).load(function(){ var windowWidth = $(window).width(); var thisLeft, thisWidth; function animateBlocks(){ // $('.animated').each(function(){ // thisLeft = $(this).offset().left; // thisWidth = $(this).width(); // if(thisLeft < windowWidth ){ // $(this).addClass('fadeInUp'); // }else{ // $(this).removeClass('fadeInUp'); // } // }); $('h2').each(function(){ var title = $(this); thisLeft = $(this).offset().left; thisWidth = $(this).width(); if(thisLeft < windowWidth ){ TweenMax.fromTo( title, 1, {scale: 0}, {scale: 1, ease: Elastic.easeOut.config(1, 0.5)} ); }else{ //$(this).removeClass('fadeInUp'); } }); } animateBlocks(); // Horizontal scroll var container = $('.js-page-scroll'); if(container.length){ container.mCustomScrollbar({ axis:"x", theme:"dark-3", // scrollbarPosition: 'outside', advanced:{ autoExpandHorizontalScroll:true }, autoScrollOnFocus: true, callbacks:{ whileScrolling:function(){ animateBlocks(); } } }); } $(document).on("click","a[href^='#']",function(e){ var href=$(this).attr("href"),target=$(href).parents(".mCustomScrollbar"); if(target.length){ e.preventDefault(); target.mCustomScrollbar("scrollTo",href); } }); }); main { display: flex; flex-flow: row nowrap; align-items: center; align-content: center; justify-content: space-between; } section { display: block; width: 500px; border: 1px solid #000; padding: 1rem; margin-bottom: 2rem; } .js-page-scroll { width: 100%; overflow-x: auto; } .horizontal-wow { visibility: hidden; animation-name: null; } it-1 it-2 it-3 it-4 it-5

1

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

2

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

3

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

4

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

5

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?


Вопрос: Как, при скролле, запускать событие соответствующего блока единожды (добавить класс или вывести сообщение в консоли)?
Для конкретного случая - запуск tweenMax единожды при достижении определенного блока, при обратном скролле - отмена (не запускать еще раз tweenmax).
Т.е. запуск анимации, добавление класс, alert и прочее только раз после загрузки при скролле вперед и при попадании на определенный блок (есди section-1 - console.log(item-1) \ tweenmax1 , и т.д ...).


Ответ

Решение: добавлять на каждый блок атрибут done='true' при первом запуске.
Далее на запуск функции проверяем выставлен ли атрибут, если выставлен, то ничего не делаем, если не выставлен - вызываем функцию и устанавливаем done='true'
$(window).load(function(){ var container = $('#container'); container.mCustomScrollbar({ axis:"x", theme:"dark-3", // scrollbarPosition: 'outside', advanced:{ autoExpandHorizontalScroll:true }, autoScrollOnFocus: true, callbacks:{ whileScrolling:function(){ var windowWidth = $(window).width(), thisLeft, thisWidth; $('section').each(function(){ thisLeft = $(this).offset().left; thisWidth = $(this).width(); if(thisLeft < windowWidth ){ if(!this.getAttribute("done")) { console.log($(this).attr('id')); this.setAttribute("done",true); } }else{ } }); } } }); }); main { display: flex; flex-flow: row nowrap; align-items: center; align-content: center; justify-content: space-between; } section { display: block; width: 500px; border: 1px solid #000; padding: 1rem; margin-bottom: 2rem; } .js-page-scroll { width: 100%; overflow-x: auto; }

1

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

2

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

3

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

4

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

5

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?


Баг IE: контейнер заканчивается раньше дочернего центровщика

Очень трудно было выбрать тему для данного вопроса: "У меня не так отображается, помогите!" - это не тема, но дело в том, что в данном вопросе рассматривается очередной баг Internet Explorer (то есть в других браузерах всё отображается нормально), причину которого никак не удаётся выяснить.
К задаче. У нас типичный блок .Wrapper, который имеет ширину 100% от окна, и центровщик (margin: 0 auto;) с указанными min-width и max-width

В IE следующий баг: Wrapper почему-то заканчивается раньше, чем надо, а центровщик с содержимым перекрывает следующую такую же компоновку ниже:

Такой баг был замечен уже практически на свёрстанном лендинге, а потому было очень трудно сделать минимальный работающий пример. Я постарался убрать весь лишний HTML для данного примера, но CSS тоже самое было сделать очень трудно.
Если Вы запустите пример в IE (ещё раз повторюсь, что в других браузерах всё нормально), то увидите следующее:

Расскажу о том, что обнаружил сам. Сама по себе верхняя компоновка Wrapper-Centerer-Содержимое отображается корректно (её содержимое - таблица). Баг появляется при появлении нижней комбинации. Вообще там есть внутренний контейнер с зафлоченными элементами, но всё равно неясно, в чём проблема. Естественно, везде где надо, есть overflow: hidden;


Ответ

К section добавьте flex: 1 0 auto
https://jsfiddle.net/Kniha/mLh63fao/3/
В примере добавлено через section[class$='-RootWrapper']

Как наложить текст на картинку в html?

Наука.ру - главная

Космоинфо

Погрузись в космос вместе с нами!

Новости    Вопросы   Основная


надо, чтобы и отображались прямо на картинке, а не под ней.


Ответ

Наука.ру - главная

Космоинфо

Погрузись в космос вместе с нами!

Новости    Вопросы   Основная


Ошибка Failed to re-package resources

Помогите определить в чем ошибка и как ее исправить. Спасибо.
Проект не обновленный, поддерживает версию Android 4.0 API level 14 и наблюдаю следующие ошибки:
CommandInvokationFailure: Failed to re-package resources. E:\AD\sdk\build-tools\25.0.0\aapt.exe package --auto-add-overlay -v -f -m -J "gen" -M "AndroidManifest.xml" -S "res" -I "E:\AD\sdk\platforms\android-27\android.jar" -F bin/resources.ap_ --extra-packages com.appodeal.ads.unity:com.facebook.android:com.google.android.gms:com.google.unity:com.appodeal.inmobi.unity:com.google.android.gms.ads.impl:com.google.android.gms.ads:com.google.android.gms.base:com.google.android.gms:com.google.android.gms.clearcut:com.google.android.gms.gass:com.google.android.gms.location:com.google.android.gms.tasks:android.support.compat:android.support.coreui:android.support.coreutils:android.support.fragment:android.support.mediacompat:android.support.v4:com.unity3d.ads:com.unity3d.ads.android:com.appodeal.yandexmetrica.unity -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\facebook
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\google-play-services_lib
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\play-services-ads-9.8.0
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\play-services-ads-lite-9.8.0
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\play-services-base-9.8.0
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\play-services-basement-9.8.0
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\play-services-clearcut-9.8.0
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\play-services-gass-9.8.0
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\play-services-location-9.8.0
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\play-services-tasks-9.8.0
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\support-compat-25.2.0
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\support-core-ui-25.2.0
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\support-core-utils-25.2.0
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\support-fragment-25.2.0
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\support-media-compat-25.2.0
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\support-v4-25.2.0
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unity-ads
es" -S "E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es"
stderr[ E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_button_audio_toggle.xml:2: note: removing attribute http://schemas.android.com/apk/res/android:paddingStart from E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_button_audio_toggle.xml:61: note: removing attribute http://schemas.android.com/apk/res/android:layout_marginStart from E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_button_audio_toggle.xml:27: note: removing attribute http://schemas.android.com/apk/res/android:layout_alignParentStart from E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_button_audio_toggle.xml:27: note: removing attribute http://schemas.android.com/apk/res/android:layout_marginStart from E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_button_audio_toggle.xml:52: note: removing attribute http://schemas.android.com/apk/res/android:layout_marginStart from E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_button_audio_toggle.xml:44: note: removing attribute http://schemas.android.com/apk/res/android:layout_marginStart from E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_button_audio_toggle.xml:19: note: removing attribute http://schemas.android.com/apk/res/android:layout_alignParentStart from E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_button_audio_toggle.xml:10: note: removing attribute http://schemas.android.com/apk/res/android:layout_marginStart from E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_button_audio_toggle.xml: note: using v17 attributes; synthesizing resource com.oriplay.lamphead:layout/unityads_button_audio_toggle for configuration v17. E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_button_pause.xml:8: note: removing attribute http://schemas.android.com/apk/res/android:layout_marginStart from E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_button_pause.xml: note: using v17 attributes; synthesizing resource com.oriplay.lamphead:layout/unityads_button_pause for configuration v17. E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_view_video_play.xml:92: note: removing attribute http://schemas.android.com/apk/res/android:layout_alignParentStart from E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_view_video_play.xml:57: note: removing attribute http://schemas.android.com/apk/res/android:layout_alignParentEnd from E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_view_video_play.xml:57: note: removing attribute http://schemas.android.com/apk/res/android:layout_marginEnd from E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_view_video_play.xml:44: note: removing attribute http://schemas.android.com/apk/res/android:layout_marginEnd from E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_view_video_play.xml:29: note: removing attribute http://schemas.android.com/apk/res/android:layout_marginStart from E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_view_video_play.xml: note: using v17 attributes; synthesizing resource com.oriplay.lamphead:layout/unityads_view_video_play for configuration v17. E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\google-play-services_lib
es\values\common_attrs.xml:13: error: Attribute "imageAspectRatioAdjust" already defined with incompatible format. E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\play-services-base-9.8.0
es\values\values.xml:34: Original attribute defined here. ] stdout[ Configurations: (default)
Files: drawable\unityads_background_button_pause.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\drawable\unityads_background_button_pause.xml drawable\unityads_icon_play.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\drawable\unityads_icon_play.xml drawable\unityads_icon_speaker_base.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\drawable\unityads_icon_speaker_base.xml drawable\unityads_icon_speaker_triangle.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\drawable\unityads_icon_speaker_triangle.xml drawable\unityads_icon_speaker_waves.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\drawable\unityads_icon_speaker_waves.xml layout\unityads_button_audio_toggle.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_button_audio_toggle.xml layout\unityads_button_pause.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_button_pause.xml layout\unityads_view_video_paused.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_view_video_paused.xml layout\unityads_view_video_play.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_view_video_play.xml values\strings.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\values\strings.xml AndroidManifest.xml Src: () AndroidManifest.xml
Resource Dirs: Type drawable drawable\unityads_background_button_pause.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\drawable\unityads_background_button_pause.xml drawable\unityads_icon_play.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\drawable\unityads_icon_play.xml drawable\unityads_icon_speaker_base.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\drawable\unityads_icon_speaker_base.xml drawable\unityads_icon_speaker_triangle.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\drawable\unityads_icon_speaker_triangle.xml drawable\unityads_icon_speaker_waves.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\drawable\unityads_icon_speaker_waves.xml Type layout layout\unityads_button_audio_toggle.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_button_audio_toggle.xml layout\unityads_button_pause.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_button_pause.xml layout\unityads_view_video_paused.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_view_video_paused.xml layout\unityads_view_video_play.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\layout\unityads_view_video_play.xml Type values values\strings.xml Src: () E:\A_Project\oriplaygames-lamphead-AndroidBuild-333333333333\Temp\StagingArea\android-libraries\unityads
es\values\strings.xml Including resources from package: E:\AD\sdk\platforms\android-27\android.jar applyFileOverlay for drawable trying overlaySet Key=common_full_open_on_phone.png trying overlaySet Key=common_google_signin_btn_icon_dark.xml trying overlaySet Key=common_google_signin_btn_icon_dark_disabled.9.png trying overlaySet Key=common_google_signin_btn_icon_dark_focused.xml trying overlaySet Key=common_google_signin_btn_icon_dark_normal.9.png trying overlaySet Key=common_google_signin_btn_icon_dark_pressed.9.png trying overlaySet Key=common_google_signin_btn_icon_light.xml trying overlaySet Key=common_google_signin_btn_icon_light_disabled.9.png trying overlaySet Key=common_google_signin_btn_icon_light_focused.xml trying overlaySet Key=common_google_signin_btn_icon_light_normal.9.png trying overlaySet Key=common_google_signin_btn_icon_light_pressed.9.png trying overlaySet Key=common_google_signin_btn_text_dark.xml trying overlaySet Key=common_google_signin_btn_text_dark_disabled.9.png trying overlaySet Key=common_google_signin_btn_text_dark_focused.xml trying overlaySet Key=common_google_signin_btn_text_dark_normal.9.png trying overlaySet Key=common_google_signin_btn_text_dark_pressed.9.png trying overlaySet Key=common_google_signin_btn_text_light.xml trying overlaySet Key=common_google_signin_btn_text_light_disabled.9.png trying overlaySet Key=common_google_signin_btn_text_light_focused.xml trying overlaySet Key=common_google_signin_btn_text_light_normal.9.png trying overlaySet Key=common_google_signin_btn_text_light_pressed.9.png trying overlaySet Key=cast_ic_notification_0.png trying overlaySet Key=cast_ic_notification_1.png trying overlaySet Key=cast_ic_notification_2.png trying overlaySet Key=cast_ic_notification_connecting.xml trying overlaySet Key=cast_ic_notification_on.png trying overlaySet Key=common_full_open_on_phone.png baseFile 0 has flavor hdpi-v4 baseFile 1 has flavor xhdpi-v4 overlayFile 0 has flavor mdpi-v4 overlayFile 1 has flavor tvdpi-v4 overlayFile 2 has flavor hdpi-v4 overlayFile 3 has flavor xhdpi-v4 overlayFile 4 has flavor xxhdpi-v4 nothing matches overlay file common_full_open_on_phone.png, for flavor mdpi-v4 nothing matches overlay file common_full_open_on_phone.png, for flavor tvdpi-v4 found a match (2) for overlay file common_full_open_on_phone.png, for flavor hdpi-v4 found a match (3) for overlay file common_full_open_on_phone.png, for flavor xhdpi-v4 nothing matches overlay file common_full_open_on_phone.png, for flavor xxhdpi-v4 trying overlaySet Key=common_ic_googleplayservices.png trying overlaySet Key=common_signin_btn_icon_dark.xml trying overlaySet Key=common_signin_btn_icon_disabled_dark.9.png trying overlaySet Key=common_signin_btn_icon_disabled_focus_dark.9.png trying overlaySet Key=common_signin_btn_icon_disabled_focus_light.9.png trying overlaySet Key=common_signin_btn_icon_disabled_light.9.png trying overlaySet Key=common_signin_btn_icon_focus_dark.9.png trying overlaySet Key=common_signin_btn_icon_focus_light.9.png trying overlaySet Key=common_signin_btn_icon_light.xml trying overlaySet Key=common_signin_btn_icon_normal_dark.9.png trying overlaySet Key=common_signin_btn_icon_normal_light.9.png trying overlaySet Key=common_signin_btn_icon_pressed_dark.9.png trying overlaySet Key=common_signin_btn_icon_pressed_light.9.png trying overlaySet Key=common_signin_btn_text_dark.xml trying overlaySet Key=common_signin_btn_text_disabled_dark.9.png trying overlaySet Key=common_signin_btn_text_disabled_focus_dark.9.png trying overlaySet Key=common_signin_btn_text_disabled_focus_light.9.png trying overlaySet Key=common_signin_btn_text_disabled_light.9.png trying overlaySet Key=common_signin_btn_text_focus_dark.9.png trying overlaySet Key=common_signin_btn_text_focus_light.9.png trying overlaySet Key=common_signin_btn_text_light.xml trying overlaySet Key=common_signin_btn_text_normal_dark.9.png trying overlaySet Key=common_signin_btn_text_normal_light.9.png trying overlaySet Key=common_signin_btn_text_pressed_dark.9.png trying overlaySet Key=common_signin_btn_text_pressed_light.9.png trying overlaySet Key=ic_plusone_medium_off_client.png trying overlaySet Key=ic_plusone_small_off_client.png trying overlaySet Key=ic_plusone_standard_off_client.
Что я пробовал:
менял версии build-tools 23.0.1 и до 25, не помогло. выставил один и тот же во всех имеющихся манифестов minSDKVersion и соответствующий targetSDKVersion, тоже не помогло.
Содержатся такие плагины:
OpenIAB FaceBook Appodeal UnityAds Admob Google Play Services версии 7571000


Ответ

Похоже на дублирование библиотек. Некоторые плагины тянут с собой доп. библиотеки. Очень часто support-v4. И они, как правило, разные версии имеют.
Посмотрите по проекту .jar или .aar файлы, начинающиеся на support-v4 или support-v7. Нужно удалить дубликаты.
P.S. вы, смотрю, используете Appodeal, UnityAds и т.п. Лучше используйте какой-нибудь агрегатор для рекламных сетей. Мы используем ironSource. Вам на клиенте всего один раз код написать надо будет, а рекламные сети потом в админке на сайте можно будет менять (ну и .jar адаптеров докидывать по необходимости).

Сколько всего способов создать объект в java?

Сколько всего существует способов создать объект в java ? Я знаю два, с new и без него. Есть ли еще способы?
Где java использует реализацию без new, кроме сериализации?


Ответ

Примерно такие:
public static void main(String[] args) { Test test = new Test(); Class testClass = Class.forName("Test"); Test test1 = testClass.newInstance(); EnumTest enumTest = EnumTest.ONE; }
class Test{}
enum EnumTest{ONE;}

Преобразование ломаной линии

Я имею неравномерную сетку в виде координат узлов в двумерном пространстве Узлы сетки хранятся в одномерном векторе, где нумерация снизу-вверх слева-направо

Также мне дана ломаная монотонная линия (обозначена синим цветом на рисунке), из которой необходимо получить ломаную линию, проходящую через узлы сетки (обозначено красной линией на рисунке).
Количество точек ломаной линии не совпадает с количеством точек результирующей ломаной.
Есть ли у кого-нибудь идеи по решению данной задачи?


Ответ

0) Учащаем точки ломаной: в цикле определяем расстояние между соседними точками (D) у ломаной, если это расстояние больше, чем расстояние диагонали ячейки сетки (d), то вставляем дополнительною точку.

Это шаг предобработки ломаной. В конце объясню зачем это нужно
1) Определяем ближайший узел (curr_node) к начальной точке (p) исходной ломаной
Далее в цикле:
2) Определяем соседние узлы для curr_node (соседями не считать предыдущий посещенный узел)

3) Определяем расстояние от curr_node и от его соседних узлов до следующей точки ломаной (p_next).

4) Если расстояние от curr_node до p_next меньше, чем минимальное расстояние от его соседей до p_next, то p_next станет следующей точкой ломаной, иначе "посещаю" следующий узел сетки (тот соседний узел, который ближе всего к точке p_next)
Далее возвращаемся к шагу 2
В итоге получаем такую картину посещения узлов

т.е. собирая посещенные узлы (черные), получаем такую ломаную, проходящую по узлам сетки:

А теперь покажу зачем нужно было делать нулевой шаг:
Как видно из этих двух рисунков, первый вариант неверный. Вставкой дополнительных точек, добьемся правильного результата

Как обновить autowired коллекцию Spring

Имеется коллекция объектов
@Autowired private List objects;
В рантайме создаю новую реализацию интерфейса SomeInterface, Как сделать , чтобы спринг обновил эту коллекцию?


Ответ

Можете сделать так:
@Autowired private ApplicationContext context;
public Collection getList(){ return context.getBeansOfType(SomeInterface.class); }
Но, чтобы это правильно работало, необходимо вашу новую реализацию зарегистрировать в контексте spring'a .
Например так:
((DefaultListableBeanFactory)context .getAutowiredCapableBeanFactory()) .registerSingleton(new SomeInterfaceImpl());

JQuery timer не могу запустить вперед

Я написал код, и он где то дает сбой, не могу понять почему, он тупо не выводит числа.Помогите разобраться почему`
var _Seconds = $('.timer').text(), int; int = setInterval(function() { if (_Seconds > 0) { _Seconds++; $('.timer').text(_Seconds); } }, 1000);
23 000 000+ `


Ответ

Потому что $('.timer').text() возвращает строку, а строка "23 000 000+" непреобразуема в число.
var _Seconds = +$('.timer').text(), int; int = setInterval(function() { if (_Seconds > 0) { _Seconds++; $('.timer').text(_Seconds.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ") + "+"); } }, 1000); 23000000
var _Seconds = +$('.timer').text(); function go() { if (_Seconds > 0) { _Seconds++; $('.timer').text(_Seconds.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ") + "+"); } var millisec = Math.ceil(Math.random()*10) * 500; console.log("time in seconds: ", millisec/1000); setTimeout(go, millisec); } go(); 23000000