Страницы

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

четверг, 21 марта 2019 г.

Можно ли писать на С++ со сборщиком мусора?

Пишу на С/С++, но вижу, что языки со сборкой мусора набирают популярность. Опять же надоело искать утечки памяти. В связи с этим вопрос:
Есть ли сейчас технологии, чтобы писать на С++, но пользоваться сборщиком мусора? Типа завел в программе объект - сборщик мусора и все операторы new перенаправляются на него, а он следит за освобождением памяти?


Ответ

Есть давняя древняя классика: http://www.hboehm.info/gc/
Дисклеймер: сам не пользовался ни разу.

Как привести объект базового типа к производному, зная Type?

Упрощенно имею следующее:
Type type; //тип класса, производного от Request (в данном случае ConcretRequest) Request request;
Нужно сделать следующее:
ConcretRequest concretRequest = (ConcretRequest)request;
Как это сделать?
Update:
Мне это нужно для передачи данных на сервер. Объекты классов, производных от Request, являются контейнерами для данных. На стороне клиента я их сериализую и создаю объект класса, содержащего результат сериализации и тип сериализованного объекта:
public class RequestPacket { public Type type; public byte[] requestBytes; }
Сериализую RequestPacket и отправляю на сервер. На сервере десериализую в RequestPacket. Далее мне необходимо десериализовать requestBytes в экземпляр класса, производного от Request
У меня есть ощущение, что я изобретаю велосипед. Но никак не могу найти, как это можно сделать проще.


Ответ

У вас в массиве байт (а затем и в поле Request request) лежит готовый объект сразу нужного типа, который где-то далее при обработке нужно привести к конкретному типу.
Для примера, пусть это будет LoginRequest
Request request = (Request)binaryFormatter.Deserialize(memoryStream);
if (type == typeof(LoginRequest)) { LoginRequest loginRequest = (LoginRequest)request; // ... дальнейшая работа с loginRequest ... }

Cоздание и распространение пакета PHP+JS

Есть простая фреймворконезависимая библиотека на PHP для вывода статистики. К ней есть фронтенд, строящий диаграммы на JS+CSS, требующий еще и Сhart.js в зависимостях. Как распространять данную связку целиком? Сразу говорю, что бэкенд без фронтенда хоть и будет работать, но вряд ли кому-то пригодится. Весь цимес именно в связке.
Пока в голову пришли только такие варианты.
Все вместе - PHP+JS+СSS через Сomposer и какой-нибудь asset-менеджер. Разбить на два репозитория и распространять бэкенд - через Сomposer, а фронтенд через NPM/Bower. Использовать один репозиторий, но фронтенд ставить через NPM/Bower, а бэкенд через Сomposer.
Может есть еще способы? Как обычно распространяются подобные проекты?


Ответ

Давайте так рассуждать: фронтэнд от вашей библиотеки по-отдельности бесполезен.
Поэтому вижу только вариант распространения через Composer, с выкладкой кода на Github. Какую-то работоспособную версию Chart.js, конечно, прикладывайте к проекту, лицензия MIT это позволяет
Для удобства обновления Chart.js можно приложить и package.json, отметив этот факт в Readme.
Так можно получить из одного источника работоспособную библиотеку и сразу начинать ее использовать.

Kotlin, как задать абстрактный массив заданного размера

Споткнулся на пустом месте...
Надо определить абстрактное свойство типа IntArray с заданным количеством элементов
Т.е. как-то так надо
abstract val margins:IntArray[4]
или
abstract val margins:Array[4]
Чтобы в дочерних классах нельзя было переопределить массивом с отличным количеством элементов. Так вообще можно делать или я хочу странного?
UPD
Т.е. чтобы в наследнике было так
override val margins = intArrayOf(10, 20, 30, 40)
А вот на такое ругалось на этапе компиляции
override val margins = intArrayOf(10, 20, 30)
override val margins = intArrayOf(10, 20, 30, 40, 60)


Ответ

Самым адекватным решением (в моем случае) оказалось использование data class с перегруженным оператором get
data class MarginArray(val left: Int, val top: Int, val right: Int, val bottom: Int) { private val _values = arrayOf(left, top, right, bottom) operator fun get(i: Int): Int = _values[i] }
Так как мне, по сути, был нужен только синтаксис доступа как к массиву, то хватило перезагрузки get, но никто не мешает добавить все необходимое перегрузкой операторов и проксированием методов к приватному полю _values, например:
fun toList() = _values.toList() fun iterator() = _values.iterator()

Как обязать использовать 32-битное обращение к структуре?

Есть некая структура с битовыми полями. Допустим
struct _example{ unsigned f10:1; unsigned f11:1; unsigned f2:2; unsigned f4:4; unsigned f8:8; unsigned f16:16; };
При обращении к f10 в виде а10|=1 формируется код orb $1,(%rcx), а нужен orl $1,(%rcx). Регистр %rcx для примера, содержит адрес начала структуры.
Можно соответствующие переменные объявлять volatile, но это решение подходит для самого первого поля.
Если подумать, то компилятор не может определить границы 32-битных слов в структуре, поэтому обращается к байтам. https://gcc.godbolt.org/z/17JQWM


Ответ

Это невозможно. Компилятор не может рассчитать 32-битные границы.

Выдернуть ВСЕ значения атрибута bigimg используя BeautifulSoup

Назрел такой вопрос. Только начал изучать питон, используя библиотеку BeautifulSoup задался вопросом. Есть HTML код, к примеру:
MY-520 Portable Ultrasonic Nebulizer Atomized Inhaler 520 MY-520 Portable Ultrasonic Nebulizer Atomized Inhaler 520
Мне нужно выдернуть все ссылки на большие изображения, которые находятся в атрибуте bigimg=
Написал такую строчку:
itemImages = soup.find("div", "scrollableDiv").findAll("img")
но как выдернуть именно ВСЕ значения атрибута bigimg не представляю. Может быть кто-то сталкивался с подобной проблемой, буду признателен.


Ответ

К сожалению не знаю библиотеку beautiful soap , но знаю как решить вашу проблему регекспами. допустим весь хтмль код у вас содержится в переменной html import re big_imgs = re.findall(r'bigimg="(.*?)"', html) в big_imgs у вас массив со всеми значениями внутри bigimg. например если бы приведены вами хтмль код засунуть в переменную html >>> big_imgs = re.findall(r'bigimg="(.*?)"', html) >>> big_imgs ['/uploads/201103/source-img/MY-520-Nebulizer-Atomized-Inhaler-G-44318.jpg', '/u ploads/201103/source-img/MY-520-Nebulizer-Atomized-Inhaler1298912536529-P-44318. jpg']

Ошибка прокрутки при использовании компонента ListView

На активити добавил листВью, при большом количестве элементов, при скроллинге, выделяются все элементы. Хотелось бы убрать этот эффект =)


public class ListAdapter extends ArrayAdapter implements OnClickListener, OnCreateContextMenuListener {
private List tasks;
public ListAdapter(Context context, List tasks) { super(context, R.layout.rowlayout, tasks); this.tasks = tasks;
}
static class ViewHolder { public TextView title, timeField; public Date dateStart; public Date dateFinish; public ImageView icon; }
Task task; ViewHolder holder; long time; ArrayList taskList = new ArrayList();
@Override public View getView(int position, View convertView, ViewGroup parent) { task = tasks.get(position);
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.rowlayout, null);
holder = new ViewHolder(); holder.icon = (ImageView) view.findViewById(R.id.subj_icon); holder.title = (TextView) view.findViewById(R.id.title); holder.timeField = (TextView) view.findViewById(R.id.start_date); view.setTag(holder); } else { holder = (ViewHolder) view.getTag(); } // view.setTag(holder); view.setTag(R.id.progressBar, task); holder.title.setText(task.getTitle()); holder.timeField.setText(Utility.formatDate(task.getDateStart()) + " - " + Utility.formatDate(task.getDateEnd()));
view.setOnClickListener(this); updateIcon();
return view; }
public void updateIcon() { int i = task.getPriority(); int excellent = task.getComplet(); if (excellent != 100) { switch (i) { case 0: holder.icon.setImageResource(R.drawable.btn_rating_star_off_normal); break; case 1: holder.icon.setImageResource(R.drawable.btn_rating_star_off_pressed); break; case 2: holder.icon.setImageResource(R.drawable.btn_rating_star_off_selected); break; default: break; } } else { switch (i) { case 0: holder.icon.setImageResource(R.drawable.btn_rating_star_on_normal); break; case 1: holder.icon.setImageResource(R.drawable.btn_rating_star_on_pressed); break; case 2: holder.icon.setImageResource(R.drawable.btn_rating_star_on_selected); break; default: break; } } }
public void onClick(View v) { Intent intent = new Intent(getContext(), TaskActivity.class); intent.putExtra(IDKeys.UID, ((Task)v.getTag(R.id.progressBar)).getID()); getContext().startActivity(intent);
} /**************************************************************************************** * * Context Menu * ****************************************************************************************/
public static final int IDM_DELETE = 102; public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { menu.add(Menu.NONE, IDM_DELETE, Menu.NONE, "DELETE"); }
}
UPD.1
на рис.1 (со звездочками) - ListView, (прилагается его код) при попытке его прокрутить пальцем на экрана девайса(или в эмуляторе), получаем -результат, на рис. 2. Т.е. все элементы выделяются, как один


Ответ

Подставил на свой row_layout.xml фон - эффект пропал....

Linq to sql проблема с ColumnAttribute(Name)

public class DataColumnStructure : IGetData { [Column(Name = "id")] public int Id { get; set; }
[Column(Name = "name")] public string Name { get; set; }
[Column(Name = "description")] public string Description { get; set; }
[Column(Name = "id_parent")] public int ParentId { get; set; } } public class MasterDataContext : DataContext { public IEnumerable GetColumns(int objectId) { return ExecuteQuery (GetColumns_Sql("sysCol.object_id = @p0"), new object[] {objectId}); } } Почему Parent_id не хочет присваиваться при указанном [Column(Name = "id_parent")]? Если же зделать так public int Id_Parent { get; set; }, то всё вытаскивается.


Ответ

Использовал эту фичу и не сталкивался с подобной проблемой. Есть мысль, что это из-за знака подчёркивания. Я бы порекомендовал в запросе явно указать SELECT id_parent AS ParentID FROM ...

Масштабирование картинок из drawable

Здравствуйте! Суть в следующем. Есть самодельное меню из картинок, при портретной ориентации находится вверху при ландшафтной слева. Вначале все прекрасно масштабировалось при нахождении картинок в drawable, в зависимости от разрешения. После того как я отправил загрузил код на SVN сервер. Друго пользователь изменил некоторые файлы, они отношения не имеют к формированию изображения, и масштабировать перестало. Использовал IDEA 10.5, после заливания перешел на 11 версию. Android 2.1, а коллеги Android 2.1-update1. Сверял все файлы одинаковые, вчем может быть дело?


Ответ

Перестаньте использовать SVN. В 3-м тысячилетье есть более правильные SCM-системы

Как не потеряться в «большом» проекте? (карта веб сервиса + клиента)

Как вы документируете, планируете, рисуете общую схему проекта, чтобы не держать всё в голове и в любой момент вернуться, и быстро въехать? Напр. относительно простой веб-сервис и его клиент. Простой протокол их общения для CRUD и ещё чуть-чуть. Сервис подключается ещё к Амазоновским сервисам для хранения данных. Клиент внутри себя имеет мультитредовые цепочки событий. Одна и та же сущность немного по-разному представляется внутри клиента (ActionScript), в сервере (php) и хранится в БД (Amazon SimpleDB) — различия типа пустой текстовой строки VS. null, строка/массив/сериализованный объект. Стоит это пытаться уместить в одной схеме, или разбить отдельно протоколы, отдельно алгоритмы и события внутри клиента, отдельно схема классов? Далёк от планирования и раньше особо не заморачивался рисованием диаграмм, но тут впервые ощущаю потребность в какой-то системе. Поделитесь Вашей?


Ответ

Есть классика, предложенная ещё со времен ООП: многоуровневая схема. Есть общая схема проекта (на уровне модулей). Есть внутренняя схема модулей (можно несколько детализаций, пока не удовлетворит). Если нужно - рисуется схема вызовов. Если нужно делает таблица (много таблиц) о правилах обмена данными.

Как сделать автоматическое монтирование расшаренной по сети папки с полными правами на изменение?

Сейчас в /etc/fstab прописано: //192.168.19.90/ExampleFolder /mnt/exampleFolder cifs auto,user,iocharset=utf8,uid=1000,umask=000,username=john,password=pa$s 0 0 В итоге получается: root@ubuntusrv:/mnt# ls -la drwxr-xr-x 1 root root 12599296 2012-12-06 13:35 exampleFolder А надо чтобы было drwxrwxrwx. Как изменить?


Ответ

Если я все правильно понимаю, то достаточно на удаленной и на локальной машине сделать: chmod 777 exampleFolder

Opensource проекты для получения опыта [закрыт]

Здравствуйте. Просматривая вакансии на Java программиста в интернете, можно заметить, что даже для джуниура почти везде нужно 1-2 года опыта работы. Много раз читал, что для получения реального опыта программирования на Java можно принять участие в разработке какого-нибудь опенсорс проекта(забесплатно :D). Скажите пожалуйста, как найти такие проекты и предложить себя в качестве кандидатуры :) В теории я уже достаточно хорошо разобрался : в Java SE и основах Java EE(Servlets, JSP, JSF), знаю основы SQL, HTML, CSS, JavaScript.


Ответ

даже для джуниура почти везде нужно 1-2 года опыта работы. Это еще что. Мне попадались вакансии Senior Ruby Developer с 6+ годами опыта, хайлоадом и всем таким, не старше 23 лет. ) По сабжу. Если немного покурите Spring MVC, Hibernate и JQuery, то можете попробоваться на один из проектов JTalks. Ребята разрабатывают набор компонент для развертывания форумов/блогов/ всего такого с тесной взаимной интеграцией. Первый релиз уже состоялся и можно посмотреть что получилось, но работы еще много. Опыт командной разработки для новичка (да и не только) будет отличный.

Ajax: получение части кода со страницы

Нужно получить часть кода из блока #id с другой страницы как с помощью .load('url #id'), но .load() не получает код скриптов внутри #id
function ocmenu(linkurl){ $.ajax({ url: linkurl, cache: true }).done(function( html ) { $('.new').append(html); }); }
html.filter('#id') не работает


Ответ

Наверное надо попробовать так, аякс возвращает Вам строку, чтобы воспользоваться функциями jQuery Вам надо преобразовать в jQuery объект: ... .done(function(html){ $(html).filter('#id'); }); ...

Элементы ActionBar в Gmail

Здравствуйте!
Возникла проблема с элементом в ActionBar помеченным как 'android:showAsAction="never"' - этот элемент создается когда нет кнопки menu у смартфона.
ab_notifications.xml


strings.xml
App Notifications
NotificationActivity.java
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.ab_notifications, menu); return true; }
На планшете это выглядит так (у планшета нет кнопки menu):
На смартфоне это выглядит так (итем Overview появляется после нажатия кнопки menu):

НО, всё это фигня какая-то, так как приложение Gmail опять отличилось:


Как они сделали так, что на смартфоне кнопка menu не выводит ничего, а этот элемент всегда отображается в ActionBar?


Ответ

ActionBar на Android < 3.0 будет всегда показывать внизу. android:showAsAction="never" означает, что этот элемент меню будет внутри "⋮".

Phalcon и валидация форм

Все привет. Кто сталкивался с компонентом PhalconValidation? Я, прочитав документацию, не могу понять, как производить валидацию, набросал вот такой вот подход: public function initialize() { $this->add('name', new PresenceOf(array( 'message' => 'Вы не заполнили Имя и Фамилию' )));
$this->add('name', new RegexValidator(array( 'pattern' => '/^[а-яА-ЯёЁa-zA-Z-]+$/ui', 'message' => 'Имя и Фамилия могут содержать только буквы и тире' )));
$this->add('name', new StringLength(array( 'max' => 50, 'min' => 5, 'messageMaximum' => 'Имя и Фамилия не может содержать больше 50 символов', 'messageMinimum' => 'Имя и Фамилия не может содержать меньше 5 символов' )));
$this->add('email', new PresenceOf(array( 'message' => 'Вы не заполнили Email адрес' )));
$this->add('email', new Email(array( 'message' => 'Не корректный Email адрес' )));
$this->add('password', new PresenceOf(array( 'message' => 'Вы не заполнили Пароль' )));
$this->add('password', new StringLength(array( 'min' => 8, 'minimumMessage' => 'Пароль не может быть короче 8 символов' )));
$this->add('confirm', new PresenceOf(array( 'message' => 'Вы не заполнили Подтверждение пароля' )));
$this->add('password', new Confirmation(array( 'message' => 'Пароли не совпадают', 'with' => 'confirm' ))); } Это неправильный подход, потому что если формы пустые, ошибки всплывают все, а не те, что проверяют форму на пустоту. Как исправить такое положение? И да, если установить 'cancelOnFail' => true, то валидация не пройдёт дальше той валидации, которая имеет этот параметр первая в очереди. UPD 06.11.14: Приведу пример валидации. Есть 4 поля, к примеру (имя/емэйл/пароль/и подтверждение пароля). Первым делом валидация проверяет заполнены поля или нет, потом поэтапно каждое поле, то есть изначально он проверяет все поля на пустоту, а потом все поэтапно, и поля не связаны между собой, за исключением пароля, и его подтверждения. Как то так.


Ответ

В чем проблема производить валидацию в два этапа и считать сообщения по выходу с первого? Зачем нужен PresenceOf, если для этого поля уже работает StringLength/Confirmation/Email? Phalcon, конечно, фреймворк с прибабахом, и валидация должна идти по группам, приложение разбиваться по неймспейсам, а объявление всего и вся через анонимные функции - это откровенная laravel-блевня, но здесь-то и задачи как таковой не стоит. Обновление @Bastian, если вы уже в самой задаче бьете ее на два этапа? Валидация одна, этапов два. Хотя объектов валидации будет два, наверное, мне лень было так глубоко лезть

Как восстановить выделение текста в EditText после выхода из ActionMode

В терминологии могу путаться. В Android совсем недавно. Создаю обычный проект с BlankActivity.
activity_main.xml



MainActivity.java
package pro1c.net.testactionmode;
import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem;
public class MainActivity extends AppCompatActivity{
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true; }
@Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
Запускаю на выполнение. Выделяю текст и выхожу из ActionMode.

Выделение пропадает. Курсор устанавливается туда где раньше был конец выделения.

Вопрос: Как сохранить выделение после выхода из ActionMode?
Я попробовал решить так:
Создал SelectionEditText.java (Был найден тут https://eyes-free.googlecode.com/svn/trunk/ime/latinime/src/com/googlecode/eyesfree/inputmethod/latin/tutorial/SelectionEditText.java) Он позволяет поймать событие изменения выделения текста.
SelectionEditText.java
package pro1c.net.testactionmode;
import android.content.Context; import android.util.AttributeSet; import android.widget.EditText;
public class SelectionEditText extends EditText { private SelectionListener mSelectionListener = null;
private int mOldSelStart = 0; private int mOldSelEnd = 0;
public SelectionEditText(Context context) { super(context); }
public SelectionEditText(Context context, AttributeSet attrs) { super(context, attrs); }
public SelectionEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); }
public void setSelectionListener(SelectionListener selectionListener) { mSelectionListener = selectionListener; }
@Override protected void onSelectionChanged(int selStart, int selEnd) { super.onSelectionChanged(selStart, selEnd);
if (mSelectionListener != null) { mSelectionListener.onSelectionChanged(this, mOldSelStart, mOldSelEnd, selStart, selEnd); }
mOldSelStart = selStart; mOldSelEnd = selEnd; }
public static interface SelectionListener { public void onSelectionChanged(SelectionEditText editText, int oldSelStart, int oldSelEnd, int selStart, int selEnd); } }
activity_main.xml Немного подправляю чтобы он использовал класс SelectionEditText



MainActivity.java Имплементирую ActionMode.Callback и SelectionEditText.SelectionListener При завершении ActionMode устанавливаю локальную переменную destroyActionMode в true. А дальше когда происходит попытка изменить выделение текста, проверяю эту переменную, и возвращаю выделение обратно на старые позиции.
package pro1c.net.testactionmode;
import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.ActionMode; import android.view.Menu; import android.view.MenuItem;
public class MainActivity extends AppCompatActivity implements ActionMode.Callback,SelectionEditText.SelectionListener{
SelectionEditText editText; private boolean destroyActionMode;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText = (SelectionEditText) findViewById(R.id.editText); editText.setCustomSelectionActionModeCallback(this); editText.setSelectionListener(this); }
@Override public void onDestroyActionMode(ActionMode mode) { destroyActionMode = true; }
@Override public void onSelectionChanged(SelectionEditText editText, int oldSelStart, int oldSelEnd, int selStart, int selEnd) { if (destroyActionMode){ editText.setSelection(oldSelStart,oldSelEnd); destroyActionMode = false; } }
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true; }
@Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); }
@Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { return true; }
@Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return true; }
@Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return true; } }
Правильно ли я сделал? Что-то подсказывает мне, что решение не совсем изящное. Есть ли другой способ сохранить выделение текста после отключения ActionMode?


Ответ

Как я понимаю, это стандартный use case, когда после выхода из action mode выделение сбрасывается, так задумано. Если по какой-то причине это надо обойти, я бы просто использовал свой ActionMode.Callback, где в onCreateActionMode() сохранял состояние выделения, а в onDestroyActionMode() восстанавливал. Так было бы проще и нагляднее.

Как узнать дату создания файла в bat?

Как можно узнать дату создания файла в BAT. У for есть переменная %%~ti, но она указывает только на дату изменения файла. А как узнать именно дату создания файла?


Ответ

Можно получить с помощью WMIC:
@echo off setlocal enabledelayedexpansion set FileName=c:\Windows
otepad.exe for %%a in ("%FileName%") do ( set File=%%~fa for /f "tokens=1* delims=," %%a in ('wmic datafile where "name='!File:\=\\!'" get 'CreationDate' /format:csv ^| find /i "%ComputerName%"') do (set CreationDate=%%b) set cYear=!CreationDate:~0,4! set cMonth=!CreationDate:~4,2! set cDay=!CreationDate:~6,2! set cHour=!CreationDate:~8,2! set cMinutes=!CreationDate:~10,2! set TimeStamp=!cDay!.!cMonth!.!cYear! !cHour!:!cMinutes! ECHO !TimeStamp! )
Вывод:
13.08.2015 22:39

Как сделать строгую последовательность Таймеров (switch/case)

Приложение загружает MediaPlayer, затем Voice recognition, если голос равен (equals) слову в условии if, то это слово ставится в TextView и загружается другой Voice recognition. Если не равно, то неверное слово ставится в TextView и загружается MediaPlayer
При первом запуске распознавания, если я отвечаю maserati, то он пропускает case 1 и сразу переходит к case 2
Как сделать СТРОГУЮ последовательность распознавания, чтобы он начинал распознавать с case 1, а это значит, если я отвечаю maserati, то он должен считать это неправильным?
public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
Timer timer1 = new Timer(); timer1.schedule(new TimerTask() {
@Override public void run() { MediaPlayer voice = MediaPlayer.create(MainActivity.this, R.raw.carMercedes); voice.start(); voice.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer voice) { voice.release(); Timer timer = new Timer("1"); timer.schedule(new TimerTask() {
@Override public void run() { Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "You may speak!"); intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en-US"); int timerId=Integer.parseInt(Thread.currentThread().getName()); startActivityForResult(intent, timerId); } }, 0); } }); } }, 0); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case 1: if (resultCode == RESULT_OK) { ArrayList results; results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); TextView speechText = (TextView) findViewById(R.id.textView1); String str = ""; for (int i = 0; i < results.size(); i++) { str += results.get(i); } if (str.equals("mercedes")) { rightAnswer(); speechText.setText(str); } else { wrongAnswer(); speechText.setText(str); } } break; case 2: if (resultCode == RESULT_OK) { ArrayList results; results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); TextView speechText = (TextView) findViewById(R.id.textView1); String str = ""; for (int i = 0; i < results.size(); i++) { str += results.get(i); } if (str.equals("maserati")) { speechText.setText(str); } else { speechText.setText(str); } } break; } }
private void wrongAnswer() { MediaPlayer voice = MediaPlayer.create(MainActivity.this, R.raw.carMaserati); voice.start(); voice.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer voice) { voice.release(); } }); } private void rightAnswer() { Timer timer = new Timer("2"); timer.schedule(new TimerTask() {
@Override public void run() { Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "You may speak!"); intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en-US"); int timerId=Integer.parseInt(Thread.currentThread().getName()); startActivityForResult(intent, timerId); } }, 0); } }
P/s. Если ответ вам неизвестен, пожалуйста, плюсуйте вопрос.


Ответ

Вы стартуете Activity на распознавание:
int timerId=Integer.parseInt(Thread.currentThread().getName()); startActivityForResult(intent, timerId);
У вас тут id потока равно 1
В итоге в onActivityResult у вас и получается в requestCode единица и срабатывает первый case. Если вы, скажем, сделаете так:
startActivityForResult(intent, 2);
Тогда в onActivityResult у вас сработает второй case

Параллельное выполнение функций на Python без threading

Есть скрипт, представляющий собой бота для Telegram. Две функции, выполняющие разные задачи.
Первая отвечает на запросы пользователя (мгновенно), другая оповещает пользователей при появлении новости на сайте, периодически запрашивая содержимое страницы (тоже мгновенно), но в ней есть таймаут (не опрашивать же сайт каждую секунду, так?), поэтому их нельзя выполнять последовательно.
Кроме использования модуля threading и запуска одной из функций в режиме демона, другого решения не нашел. Не слишком ли это, использовать такой модуль только лишь для того, чтобы запустить простую функцию-демон?
import threading from time import sleep
def function1(): ... sleep(timeout)
def function2(): ...
t = threading.Thread(target=function1) t.daemon = True t.start()
function2()


Ответ

Вообще я лично не вижу особых проблем с threading в данном случае. Но если вы хотите все делать в одном потоке, то это весьма просто.
У вас в function2(), которая отвечает на запросы пользователя, скорее всего ведь цикл, так? Вот в конец его и вставьте проверку, не прошло ли заданное время с момента предыдущей обработки содержимого страницы с новостями, и если прошло, производите вызов функции function1(). Получится примерно такой код (с сохранением ваших имен функций):
import time
def function1(): ...
def function2(): ...
latest_handling_ts = time.time() while True: # очередной ответ на запрос пользователя ...
# проверка, не прошло ли время timeout с момента последнего # запроса и обработки содержимого страницы с новостями now = time.time() if now - latest_handling_ts > timeout: # заданное время прошло, запрашиваем содержимое страницы # и обрабатываем его function1() latest_handling_ts = now
function2()

button скачивание файла (js,jquery)

Проблема с прорисовкой окна браузера

При ресайзе браузера или же при разворачивания на полный экран контент сайта ресайзится с задержкой (видно черный фон а потом через полсекунды контент перерисовывается). может кто нибудь сталкивался с этим. Что делать?


Ответ

Сделал меньше нагрузку на обрабюотчик + убрал фон, сделал белый, теперь по крайней мере не так заметно когда перерисовывается

Почему при условии “false”, трассировка входит в блок “true”

Как-то не понятно отрабатывает трассировка кода:
begin if StrToInt(Edit1.Text) < 10 then begin showmessage('Hi'); exit; end; end;
при: "Edit1.Text = 20" и соответственно условие выдает false, компилятор тормозится на breakpoint строки "exit", но пропускает вывод сообщения. Когда по идее, в этот блок он вообще не должен попадать.


Ответ

Это оптимизация компилятора. Просто Exit; избыточен внутри блока begin..end в данном контексте. Добавьте строчку кода после первого end; и увидите, что все работает как надо.
begin if StrToInt(Edit1.Text) < 10 then begin showmessage('Hi'); exit; end; showmessage('Bye'); end;

Изменения кода в бесплатной и платной версии приложения одновременно

Есть приложение N, у него есть две версии - платная и бесплатная, у каждой версии свой ИД и свой функционал.
Допустим, мне надо внести изменение в 5-7 классов, дополнить их чем-то и в той и другой версии.
Как лучше всего и удобнее это делать ?
п.с. сейчас я пишу в одной версии, потом копирую ручками в другую.


Ответ

Используйте Flavors.
Рецепт для Android Studio:
Открываете File-Project Structure-Flavors. Там уже будет defaultConfig. Создаете два flavor'а: paid и free. Указываете для каждого из них свой ApplicationId. Остальные данные указывать не обязательно, они будут браться из defaultConfig'а (возможно могут отличаться signing config, тогда его тоже указать, а может и нет, зависит от вашего проекта). Теперь для каждого из flavor'а вы можете создать свои классы и ресурсы, они будут объединяться с имеющимся кодом (поверх). Файлы эти будут лежать рядом с main в директории src. Например:
myproject app src main java res assets ... paid java res ... free res ...
2.1. Сама структура директорий не создается, придется это делать вручную. Хотя для ресурсов, например, можно выбрать sourceSet (по дефолту там main, но можно выбрать любой нужный) и тут уже структура и файлы (если надо) создадутся. Открываете слева внизу в студии Build Variants и выбираете там нужный вам вариант запуска. Например, Module: app -> Build Variant: paidDebug. Переключаетесь на freeDebug, студия сама все пересоберет. Профит.
Ссылки по теме:
Configuring Gradle Builds An Android Studio Gradle Build Variants Example

Как происходит ответ от сервера?

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


Ответ

Обычно такой функционал делается через Socket или WebSocket.
Таким образом к одному и тому же серверу подрубаются сокетным подключением и все таксисты и все клиенты.
Соответственно все подключенные к серверу могут как слать информацию к нему, так и получать от него данные.
То есть:
Клиент отправил запрос на такси через сокет. Сервер обработал запрос, передал теми же сокетами информацию о заказе всем таксистам в указанной области. Таксист увидел заказ, нажал согласится на заказ и отправил запрос на сервер о принятии заказа. Сервер увидел запрос от таксиста и передал информацию о нем клиенту. Клиент отловил это в приложении, UI обновилось и информация о таксисте видна клиенту. При этом пока заказ не принят таким же образом по таймеру таксист может предоставлять данные клиенту о своем местоположении, например.
Можно глянуть простейший пример.
В более сложных вариантах лучше создавать отдельный поток под каждое сокетное подключение, использовать БД на сервере для сохранения каких-то постоянных данных и так далее.

Подскажите модульную систему js

Начал программировать на js, но опыта мало. Хотелось бы как на php иметь аналогию с классами. Чтобы писал в один файл модуль и потом его при необходимости подключал в файле. + Было бы преимуществом чтобы это потом можно было в 1 js файл компилировать. Подскажите пожалуйста какой фреймворк или библиотеку использовать под эти нужды? Или возможно какая то статья затрагивающая эту тему будет не лишней. Спасибо


Ответ

В современной экосистеме JavaScript можно выделить несколько подходов к разбиению кода на модули:
AMD - формат описания модулей, используемый в Require.js. На мой ( очень субъективный) взгляд описание модулей несколько избыточно. Одна из основных "фишек" - асинхронная динамическая загрузка модулей по требованию. Хотя, если не изменяет память, есть и возможность собрать весь код в один пакет. Пример описания AMD модуля:
// Описание зависимостей define(['jquery', 'foo', 'bar'], function (jquery, foo, bar) { // Определение самого модуля return function () {}; }); Common.js - подход, используемый, например, в Node.js экосистеме. Типичный модуль имеет вид:
// Импортируем зависимости var jquery = require('jquery'), foo = require('foo'), bar = require('bar');
// Экспортируем тело модуля module.exports = function() {}; UMD - комбинированный подход, позволяющий описывать модули, работающие как в AMD инфраструктуре, так и в Common.js. Является ничем иным, как средством совместимости. Модули ES2015 - специальный синтаксис, введенный в стандарт ES2015 позволяющий разбивать код на модули. Пример модуля:
// Импортируем зависимости import 'jquery' as $; import foo from 'foo'; import bar from 'bar';
// Экспортируем тело модуля export default function() {};
Плохая новость заключается в том, что ни один из подходов к описанию модулей не может работать в браузере напрямую. Вам в любом случае придется подключать некую стороннюю библиотеку для управления модулями. Для AMD - это Require.js; для Common.js - Browserify, Webpack и другие; для ES2015 - это может быть связка Browserify + Babel или что-то еще.
Для новых проектов я бы порекомендовал вам обратить внимание на ES2015 модули и на Common.js модули. Тому есть несколько причин:
Экосистема Node.js использует Common.js модули. Используя систему сборки вроде Browserify вы можете использовать npm модули. Это позволит вам писать код, который будет выполняться как на сервере, так и на клиенте. При использовании современных систем сборки вы сможете практически без проблем комбинировать модули ES2015 и Common.js Хотя сегодня в браузерах нет встроенных средств загрузки модулей ES2015, все идет к тому, что рано или поздно они появятся.
Что почитать:
https://addyosmani.com/writing-modular-js/ https://learn.javascript.ru/modules http://frontender.info/es6-modules/ https://habrahabr.ru/post/181536/ Очевидно, есть и другие статьи по теме. Google расскажет вам о них лучше меня. =)

Gradle ошибка при создании проекта

Gradle в Idea выдает следующую ошибку.
Gradle 'week1' project refresh failed Error:Нет такого файла или каталога
Gradle последней версии скачаный с оф. сайта(2.12). ОС Ubuntu 15.10. Idea 2016.1.1. Все установил, переменную GRADLE_HOME тоже. как устанавливать и прописывать смотрел в гайдах и статьях.
через apt-get install gradle тоже установил, прописал гредл хом к нему, но идея писала что неверный каталог для гредла. (при том что сам гредл этим способом установился нормально и на gradle -v отвечал нормально и jdk видел нужную)
думал еще может прав каких не хватает пробовал распаковывать скачанный архив в домашнюю директорию - тоже тщетно. помогите плиз.


Ответ

Проблема была не с Гитом в целом, а его интеграции в Идею. В настройках гредла в идее service derectory path был указан не тот. Я указал /home/den/.gradle (где den - имя пользователя в Ubuntu)и заработало.

Java Русские буквы Ubuntu server

Суть проблемы заключается в том что при передаче текстовых данных содержащих русские буквы, на стороне сервлета я вижу "???????? ???? ?????"
А теперь подробнее.
Собираю проект в IDEA, в качестве OS использую Ubuntu Desktop 14.04, запускаю на локальном TOMCAT. Проект запускается, и данные через post запрос передаются на сервлет - все работает отлично.
Собранный проект я копирую на удаленный ubuntu server 14.04 и запускаю на локальном TOMCAT сервере, все работает как надо за исключением одной проблемы - при передаче текстовых данных содержащих русские буквы post запросом на стороне сервера я вижу ???????? ???? ?????
Что я использую:
TOMCAT 8.0.33
java version "1.8.0_91" Java(TM) SE Runtime Environment (build 1.8.0_91-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)
вот такой вот JSP
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %>


Вот такой вот Сервлет
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String fio = req.getParameter("fio"); String email = req.getParameter("email");
System.out.println(fio); System.out.println(email); System.out.println(req.getCharacterEncoding()); System.out.println(resp.getCharacterEncoding());
При попытке ввести значение йцуйцу wqe@qwe.ru вот такой вывод
?????? qwe@qwe.ru UTF-8 UTF-8
Кодировка java файлов в IDEA UTF-8
Что я уже пытался делать:
Я пытался поменять\добавить в систему новые локали и теперь это выглядит таком вот образом
locale -a C C.UTF-8 en_AG en_AG.utf8 en_AU.utf8 en_BW.utf8 en_CA.utf8 en_DK.utf8 en_GB.utf8 en_HK.utf8 en_IE.utf8 en_IN en_IN.utf8 en_NG en_NG.utf8 en_NZ.utf8 en_PH.utf8 en_SG.utf8 en_US.utf8 en_ZA.utf8 en_ZM en_ZM.utf8 en_ZW.utf8 POSIX ru_RU ru_RU.cp1251 ru_RU.iso88595 ru_RU.koi8r ru_RU.utf8 ru_UA.utf8
locale LANG=ru_RU.UTF-8 LANGUAGE= LC_CTYPE="ru_RU.UTF-8" LC_NUMERIC="ru_RU.UTF-8" LC_TIME="ru_RU.UTF-8" LC_COLLATE="ru_RU.UTF-8" LC_MONETARY="ru_RU.UTF-8" LC_MESSAGES=POSIX LC_PAPER="ru_RU.UTF-8" LC_NAME="ru_RU.UTF-8" LC_ADDRESS="ru_RU.UTF-8" LC_TELEPHONE="ru_RU.UTF-8" LC_MEASUREMENT="ru_RU.UTF-8" LC_IDENTIFICATION="ru_RU.UTF-8" LC_ALL=
Я пытался установить фильтр
package xxx.filters;
import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException;
@WebFilter("/CharEncodingFilter") public class CharEncodingFilter implements Filter {
private static final String FILTERABLE_CONTENT_TYPE="application/x-www-form-urlencoded";
private static final String ENCODING_DEFAULT = "UTF-8";
private static final String ENCODING_INIT_PARAM_NAME = "encoding";
private String encoding;
@Override public void init(FilterConfig config) throws ServletException{ encoding = config.getInitParameter(ENCODING_INIT_PARAM_NAME); if (encoding == null) encoding = ENCODING_DEFAULT; }
@Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException{ String contentType = req.getContentType(); if (contentType != null && contentType.startsWith(FILTERABLE_CONTENT_TYPE)) req.setCharacterEncoding(encoding); resp.setCharacterEncoding(encoding); chain.doFilter(req, resp); }
@Override public void destroy() {
} }
И добавить этот фильтр в web.xml проекта
CharEncodingFilter orion.filters.CharEncodingFilter encoding UTF-8
CharEncodingFilter /*
Я пытался отредактировать server.xml Tomcat server и теперь он выглядит так

Буду благодарен за любую помощь.


Ответ

Проблема оказалась в Tomcat
На стороне ubuntu server, Tomcat воспринимал файлы .class в кодировке ANSI_X3.4-1968
System.out.println("File Encoding = " + System.getProperty("file.encoding"));
File Encoding ANSI_X3.4-1968
На стороне ubuntu desctop, Tomcat воспринимал файлы .class в кодировке UTF-8
System.out.println("File Encoding = " + System.getProperty("file.encoding"));
File Encoding UTF-8
Не понимаю как это возможно
Решение следующие: Необходимо редактировать catalina.sh
sudo nano /opt/tomcat/bin/catalina.sh
И задать кодировку руками. После большого системного комментария добавить строку.
export CATALINA_OPTS="$CATALINA_OPTS -Dfile.encoding=UTF-8"

Что является лучшим вариантом для эффективного выполнения непостоянных фоновых задач в ОС Android?

Для фонового выполнения задач в среде Android доступны 4 класса: HandlerThread, Thread, IntentService, AsyncTask. Использование какого класса эффективно для выполнения фоновых задач, если задачи возникают непостоянно?
Задачей в основном является получения информации из интернета. Из-за непостоянства задач непонятно какой класс использовать для достижения наилучшей эффективности.
HandlerThread хорош для выполнения частых запросов, но при редких - простой потока. Thread хорош при редких запросов, но при частых - падение производительности (создание объекта + резервирование необходимых ресурсов). AsyncTask аналогичен Thread. IntentService хорош для всех задач, но проблемы в производительности могут быть из-за частого запуска сервиса системой android.
Кто что может посоветовать?


Ответ

Вас скорее должен волновать вопрос нужно ли вам, чтобы работа завершилась до конца или особо не важно. Т.к. если вам крайне необходимо чтобы поток завершил свою работу, то однозначно - IntentService, если всё равно, то можете юзать AsyncTask, поверьте, лишнего процессорного времени он не жрёт

Развертывание deb-репозитория и ftp сервера

Настроил deb репозиторий, локально по протоколу file:/ все работает. Для того чтобы расшарить его в сеть развернул ftp сервер, который тоже работает. Выставил опцию anonymous_enable=YES. Через терминал могу подключиться как anonymous.
В source.list добавил репозиторий. При выполнении sudo apt-get update выводится
игн ftp://10.10.2.18 wily InRelease игн ftp://10.10.2.18 wily Release.gpg игн ftp://10.10.2.18 wily Release [100%] ожидание заголовков
В лог ftp сервер ничего не пишет, значит apt-get не может достучаться до машины с рерозиторием.
В чем может быть проблема?


Ответ

В лог ftp сервер ничего не пишет, значит apt-get не может достучаться до машины с рерозиторием.
неправильный вывод. файлы игнорируются потому, что сервер сообщил, что таких файлов нет. см. этот ответ: How do Ign and Hit affect apt-get update?
если бы возникли ошибки с доступом, apt так бы об этом и написал.

дополнение: насколько я понимаю, отсутствуют перечисленные файлы в каталоге /корень-вашего-ftp/dists/wily/

Самовызывающиеся функции JavaScript

(function(a){ alert(a); }(1));
(function (a) { alert(a); })(1);
В чем отличие этих функций?
Или вот из примера Стефанова:
var result = (function () { return 2 + 2; }());
(function () { alert(‘watch out!’); })();


Ответ

Разницы, в общем-то, нет. Дуглас Крокфорд посчитал что запись:
(function () { //body }());
Является правильной, а нотацию:
(function () { //body })();
Неправильной и пренебрежительно называет её "собачьи яйца" (dog balls).

Поэтому используйте ту, что больше нравится (я, к примеру, согласен с Дугласом, хотя второй вариант ничуть не раздражает). Например в Perl вообще слоганом предписано что всё должно иметь несколько путей нотации. Чем JS хуже? :)

Пуш-уведомление по установленному времени

Всем добра! Ребят, это снова я и мне нужна Ваша помощь. Я полностью переосмыслил работу со временем, с пикерами даты и прочего полезного. Имеется следующий код.

1. Метод работы со временем:
... info = (TextView)mBottomSheetDialogTime.findViewById(R.id.info); pickerDate = (DatePicker)mBottomSheetDialogTime.findViewById(R.id.pickerdate); pickerTime = (TimePicker)mBottomSheetDialogTime.findViewById(R.id.pickertime); Calendar now = Calendar.getInstance(); pickerDate.init(now.get(Calendar.YEAR), now.get(Calendar.MONTH), now.get(Calendar.DAY_OF_MONTH), null); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { pickerTime.setHour(now.get(Calendar.HOUR_OF_DAY)); pickerTime.setMinute(now.get(Calendar.MINUTE)); } else { pickerTime.setCurrentHour(now.get(Calendar.HOUR_OF_DAY)); pickerTime.setCurrentMinute(now.get(Calendar.MINUTE)); } buttonSetAlarm = (Button)mBottomSheetDialogTime.findViewById(R.id.setalarm); buttonSetAlarm.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View arg0) { Calendar current = Calendar.getInstance(); Calendar cal = Calendar.getInstance(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) cal.set(pickerDate.getYear(), pickerDate.getMonth(), pickerDate.getDayOfMonth(), pickerTime.getHour(), pickerTime.getMinute(), 0); else cal.set(pickerDate.getYear(), pickerDate.getMonth(), pickerDate.getDayOfMonth(), pickerTime.getCurrentHour(), pickerTime.getCurrentMinute(), 0); Context context = getApplicationContext(); if(cal.compareTo(current) <= 0) Toast.makeText(getApplicationContext(), "Invalid Date/Time", Toast.LENGTH_LONG).show(); else scheduleNotification(getNotification(), cal); }}); ...
2. Метод работы уведомления:
private void scheduleNotification(Notification notification, Calendar targetCal{ info.setText("


"+"Alarm is set@ "+targetCal.getTime()+"
"); Intent notificationIntent = new Intent(getBaseContext(), NotificationPublisherBroadcastReceiver.class); notificationIntent.putExtra(NotificationPublisherBroadcastReceiver.NOTIFICATION_ID, 1); notificationIntent.putExtra(NotificationPublisherBroadcastReceiver.NOTIFICATION, notification); PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), 0, notificationIntent, 0); AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); if (android.os.Build.VERSION.SDK_INT >= 19) alarmManager.setExact(AlarmManager.RTC_WAKEUP, targetCal.getTimeInMillis(), pendingIntent); else alarmManager.set(AlarmManager.RTC_WAKEUP, targetCal.getTimeInMillis(), pendingIntent); }
3. Receiver
public class NotificationPublisher extends BroadcastReceiver{
public static String NOTIFICATION_ID = "notification-id"; public static String NOTIFICATION = "notification";
public void onReceive(Context context, Intent intent){ NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); Notification notification = intent.getParcelableExtra(NOTIFICATION); int id = intent.getIntExtra(NOTIFICATION_ID, 0); notificationManager.notify(id, notification); Toast.makeText(context, "Alarm received!", Toast.LENGTH_LONG).show(); } }
4. Manifest

5. getNotification()
private Notification getNotification() { Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); Intent intent = new Intent(getBaseContext(), NotificationPublisherBroadcastReceiver.class); intent.putExtra("title", getString(R.string.notificationtitle)); intent.putExtra("text", getString(R.string.notificationtext)); PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0); NotificationCompat.Builder builder = new NotificationCompat.Builder(getBaseContext()) .setSmallIcon(R.drawable.time) .setLargeIcon(bitmap) .setContentTitle(getString(R.string.notificationtitle)) .setContentText(getString(R.string.notificationtext)) .setContentIntent(pIntent) .setAutoCancel(true) .setVibrate(new long[]{1000, 1000, 1000, 1000}) .setDefaults(Notification.DEFAULT_SOUND); return builder.build(); }

Вся проблема в том, что когда я нажимаю buttonSetAlarm, в котором вызов уведомления scheduleNotification(getNotification(), cal); уведомления приходит сразу же, а не когда я назначил время, и еще не показывается Toast.makeText(context, "Alarm received!", Toast.LENGTH_LONG).show(); из receiver (Есть подозрение на не поддержку API. У меня стоит поддержка от 15 до 23 версии, на данный момент тестирую на 23). Где я ошибаюсь? И что мне сделать, чтобы исправить? Любая помощь будет бесценной!


Ответ

Вот так регистрируется алярм для разных версий android-a.
if (android.os.Build.VERSION.SDK_INT >= 19) alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent); else alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
Плюс посмотрите какое значение достает pickerDate.getMonth(). Если возвращает 5 (май), то надо вычесть 1, так как в календарь месяца сетятся от 0 до 11.

user32.dll FindWindowEx получение текста

Как я могу получить текст с lable окна другой программы используя user32.dll? Пытаюсь найти но не получается.
int i = 0; void Button1Click(object sender, EventArgs e) {
var m = FindWindow("WindowsForms10.Window.8.app.0.33c0d9d", null); var child = FindWindowEx(m, IntPtr.Zero + i, null, null); textBox2.Text += i + GetWindowTextRaw(child); i++;
}
Вот что "говорит" Inspector по клику на lable:
How found: Mouse move (483,319) hwnd=0x00010AE0 32bit class="WindowsForms10.Window.8.app.0.33c0d9d" style=0x56010000 ex=0x10000 ChildId: 0 Interfaces: IEnumVARIANT IOleWindow Impl: Remote native IAccessible Name: "Command History:" Value: [null] Role: client (0xA) State: focusable (0x100000) Location: {l:24, t:163, w:1242, h:250} Selection: Description: [null] Kbshortcut: [null] DefAction: [null] Help: [null] HelpTopic: "" ChildCount: 12 Window: 0x10AE0 FirstChild: none : window : focusable LastChild: none : window : focusable Next: [null] Previous: [null] Left: [null] Up: [null] Right: [null] Down: [null] Other Props: Object has no additional properties Children: none : window : focusable none : window : focused,focusable "Project : " : window : focusable "1126F1_9363262_40A" : window : focusable "Run" : window : focusable "Stop" : window : focusable "Serial #" : window : focusable "1P11321126F1#2PG#SJ1641700018" : window : focusable none : window : focusable "TS128L " : window : focusable "TS128L " : window : focusable none : window : focusable


Ответ

Спустя несколько дней разобрался. Может кому пригодится.
void FindWindow(){ var hWndParent = FindWindow("WindowsForms10.Window.8.app.0.33c0d9d", null); FindChild(hWndParent); } void FindChild(IntPtr hWndParent){ EnumChildWindows(hWndParent, new EnumWindowsProc(( hWnd, lParam ) => { if (GetParent(hWnd) != hWndParent){ return true; } FindChild(hWnd); if(GetText(hWnd).StartsWith("1P11321126F1#2PG#")){ if(label1.InvokeRequired){ label1.Invoke(new MethodInvoker(delegate { label1.Text = GetText(hWnd).Trim();})); } } return true; }), IntPtr.Zero); } string GetText(IntPtr hWnd){ StringBuilder sb = new StringBuilder(WM_GETTEXTLENGTH + 100000); string text = SendMessage(hWnd, WM_GETTEXT, WM_GETTEXTLENGTH + 100000, sb).ToString(); return sb.ToString(); }

#region user32.dll delegate bool EnumWindowsProc ( IntPtr hWnd, IntPtr lParam );
[DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool EnumWindows ( EnumWindowsProc lpEnumFunc, IntPtr lParam );
[DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool EnumChildWindows ( IntPtr hWndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam );
[DllImport("user32.dll", SetLastError = true)] static extern IntPtr GetParent ( IntPtr hWnd ); [DllImport("user32.dll", SetLastError = true)] static extern int GetClassName ( IntPtr hWnd, StringBuilder lpString, int nMaxCount );
[DllImport("user32.dll", SetLastError = true)] static extern int GetWindowTextLength ( IntPtr hWnd );
[DllImport("user32.dll", CharSet = CharSet.Auto)] static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, int wParam[Out] StringBuilder lParam);
const int WM_GETTEXT = 0xD; const int WM_GETTEXTLENGTH = 0x000E; #endregion

В чем суть ковариантности и контравариантности делегатов?

Изучаю по книге работу с делегатами и есть там пример, объясняющий, что такое ковариантность и контравариантность. Решил подробнее поискать в гугле, но объяснений так и не нашел. В книге сказано, что ковариантность позволяет присвоить делегату метод, возвращаемым типом которого служит класс, производный от класса, указываемого в возвращаемом типе делегата. А контравариантность позволяет присвоить делегату метод, типом параметра которого служит класс, являющийся базовым для класса, указываемого в объявлении делегата. К сожалению в практике это так разобрать и не смог, может кто сможет разжевать данный пример подробнее или преподнести свой, более легкий?
class X { public int Val; }
class Y : X { }
//Этот делегат возвращает объект класса X и принимает объект класса Y в качестве аргумента delegate X ChangeIt(Y obj);
class CoContraVariance { //Этот метод возвращает объект класса X и имеет объект класса X в качестве параметра static X IncrA(X obj) { X temp = new X(); temp.Val = obj.Val + 1; return temp; }
//Этот метод возвращает объект класса Y и имеет объект класса Y в качестве параметра static Y IncrB(Y obj) { Y temp = new Y(); temp.Val = obj.Val + 1; return temp; }
static void Main() { Y Yob = new Y();
ChangeIt change = IncrA; X Xob = change(Yob);
Console.WriteLine("Xob: {0}", Xob.Val);
change = IncrB; Yob = (Y)change(Yob);
Console.WriteLine("Yob: {0}", Yob.Val);
Console.ReadLine(); } }


Ответ

Для начала, давайте глянем, что такое эта самая вариантность.
Пусть у нас есть два класса, Car и BMW. Очевидно, что BMW есть подкласс Car: каждая бэха является машиной.
Обычно при этом говорят так: «везде, где вы используете Car, можно использовать и BMW». Это на самом деле почти правда, но не совсем.
Пример: если у вас есть список машин, вы не можете вместо него использовать список BMW. Почему? А вот почему. Пускай вас есть List, и вы используете его как список машин. Тогда, раз это список машин, в него можно добавить и Запорожец Lanos, правильно? Вот тут-то и начинаются проблемы. Если у вас в коде написано:
List bmws = new List(); List cars = bmws; // поскольку список БМВ - это список машин cars.Add(new Lanos()); BMW bmw = bmvs[0]; // ой.
Внимательно посмотрите на этот код и подумайте над ним: он иллюстрирует проблему. (И он не откомпилируется: язык C# спроектирован так, чтобы не приводить к проблемам.) Проблема с записью в список. Если мы в список добавим произвольную машину, будет очень плохо: мы сможем нарушить гарантии, которые даёт нам система типов!
Если бы у нас был список, доступный только на чтение, то проблем бы как раз не было:
IEnumerable bmws = new List() { new BMW() }; IEnumerable cars = bmws; // а так можно //cars.Add(new Lanos()); // <-- не скомпилируется
Итак, что у нас получается? Несмотря на то, что BMW — машина, список BMW уже не обязательно является списком машин. А вот список BMW, доступный лишь на чтение, таки является списком машин.
Есть?
Теперь назад к вариантности. Мы говорим о ковариантности в общем смысле, если что-то меняется аналогичным образом. В случае наследования классов: мы можем вместо Car использовать BMW, и точно так же мы можем вместо IEnumerable использовать IEnumerable

Окей, это было длинное вступление, теперь вернёмся к теме: ковариантность делегатов. Пусть у нас есть делегат, зависящий от типа Car. Поменяем в его определении Car на BMW, можно ли новый делегат использовать вместо старого?
Давайте рассуждать логически. Если у нас есть такой делегат:
public delegate Car Replace(Car original);
(он принимает на вход Car, и выдаёт другой экземпляр Car), то можно ли вместо него подставить функцию, описывающуюся делегатов такого вида:
public BMW MyReplace(BMW original) { ... }
? Разумеется, нет, потому что делегат может принимать на вход любую функцию, а наша функция хочет только BMW. Так что здесь ковариантности нету: такую функцию нельзя использовать там, где требуется данный делегат.
А вот если наш вариантный тип данных (то есть, Car) находится лишь в позиции возвращаемого типа:
public delegate Car Create();
то на его месте можно использовать функцию такого вида:
public BMW CreateBmw() { ... }
(если подходила любая машина, то BMW тоже подойдёт).
Это и есть ковариантность делегатов: там, где от вас в коде требуется делегат, вы можете вместо него предоставить ковариантный делегат.
Пример кода, использующий это:
// это функция, принимающая делегат: Car PrepareCar(Create carCreator) { Car car = carCreator(); car.ManufacturingDate = DateTime.Now; car.Mileage = 0; return car; }
// это функция, которая ковариантна Create: она возвращает не Car, а BMW BMW BmwFactory() { var bmw = new BMW(); bmw.EnginePower = 400; return bmw; }
// вы можете использовать эту функцию как аргумент PrepareCar // хотя её сигнатура другая: return PrepareCar(BmwFactory);

Контравариантность работает в другую сторону: там вы можете использовать делегат, работающий с базовым типом там, где ожидается делегат с производным типом. Такое работает для аргументов функций:
delegate double BmwTester(BMW bmw);
void TestAndPublish(BmwTester tester) { var bmw = new BMW(); double testResult = tester(bmw); PublishResult(testResult); }
double UniversalTester(Car car) { return 5.0; }
// вы можете использовать UniversalTester, хотя у него и не совсем подходящая сигнатура TestAndPublish(UniversalTester);
Это работает по тем же причинам, что и ковариантность: если тестеру подходит любой тип машины, то он сможет работать и с BMW тоже.

Как открыть цифровую клавиатуру на телефоне при вводе в input type=“text”?

Как при вводе в input type="text" открыть на мобильных цифровую клавиатуру? Или при вводе в input type="number" ограничить всё, кроме ввода цифр и запятой? Проблем в том, что при наличию точки в конце без десятичного знака, input возвращает пустоту. Я пробовал биндить регулярки, но input type="number" вообще не реагирует на них.
Мб я вообще неправильное решение ищу? Мне нужно, чтобы при вводе цифр десятичного числа на телефоне, открывалась цифровая клавиатура и всё правильно считалось — при вводе "45." на расчёт шло "45", а не "". Причём я заметил что input type="number" пропускает точку, запятую и цифры, вот когда используется запятая, всё окей — то есть, при вводе "45," в расчёт идёт "45", а при вводе "45." в расчёт "" и результат 0.


Ответ

Поскольку при вводе input[type=number] ведёт себя не совсем адекватно при вводе точки, предлагаю вот такой костыль с input[type=hidden]. При сабмите формы берите значение из него — там всегда будет храниться нужное значение.
Немного объяснений по коду:
При событии keydown отлавливаем нажатие на точку или дробную часть (у точки на нампаде другой код) и записываем в input[type=hidden] текущее значение + точку. Также отлавливаем бекспейс + проверяем — есть ли точка в предпоследнем символе в input[type=number], и если есть, то удаляем цифру после точки. Событие keyup срабатывает уже после того, как символ появился в input[type=number] и, если его значение true, то добавляем его в input[type=hidden]. Если оно равно false + была нажата клавиша бекспейс + старое значение input[type=hidden] содержит один символ, то значит мы стерли все символы и input[type=hidden] надо приравнять пустому значению. Эти же действия дублируются на ивент input, чтобы можно было вводить значение стрелочками или колесом мыши.
var input = document.querySelector('input[type=number]'), hidden = document.querySelector('input[type=hidden]'), output = document.querySelector('output'); input.addEventListener('keydown', function(e) { if (e.keyCode === 110 || e.keyCode === 190) { hidden.value = e.target.value + '.'; } else if (e.keyCode === 8 && e.target.value.slice(-2, -1) === '.') { hidden.value = hidden.value.slice(0, -1); } }); input.addEventListener('keyup', inputProcess); input.addEventListener('input', inputProcess); function inputProcess(e) { if (input.value) { hidden.value = input.value; } else if (!input.value && e.keyCode === 8 && hidden.value.length === 1) { hidden.value = ''; } output.innerHTML = hidden.value; }

Нужны ли переменные среды для запуска java приложений?

Борюсь с проблемой распространения написанного на java приложения на компьютеры, не имеющие установленной java.
К сожалению, exe-приложения, как бы я их ни делал, получаются крайне нестабильными:
IntelliJ IDEA (exe из bundle полученного artifact даже у меня не всегда запускается) launch4j (javaw.exe мелькает в процессах лишь на секунду; jre находится в папке с приложением, это указано при создании в launch4j) etc
И я решил, что проще вынудить пользователей установить java, чем мучиться с упаковкой и прочим.

Появляется логичный вопрос: достаточно ли скачивания и установки Java (java.com/download) чтобы приложение работало стабильно и без любых ошибок, несмотря на то, jar это или exe, полученный любым из способов? Или нужно что-то ещё настраивать, устанавливать переменные среды и прочее?
Если это необходимо, придётся это автоматизировать, не все юзвери в состоянии подобное сделать :)
Если я мыслю крайне неправильно, или допускаю ошибки, из-за которых приложения становятся нестабильными и не работают, прошу указать на это и, если возможно, показать, как сделать это правильно (хотя, не знаю, как я мог допустить ошибку при создании exe через launch4j, нажав всего две кнопки).
Также, если есть более простые способы распространить java-приложение, буду рад узнать.

UPDATE: Сначала просто скинул jar из bundle человеку, у которого стоит java последней версии на компьютере, он тоже не запустился, потом собрал artifact-jar в IDEA, полученный файл тоже скинул - эффект такой же, как и с exe-шником: javaw.exe мелькает в процессах на секунду, и всё, программа не запускается. Так происходит, где бы не лежал файл. В чём проблема? Что я делаю не так?


Ответ

Для запуска написанных на Java приложений на других компьютерах, где установлена Java, не нужны переменные среды. (проверено) Скачивания и установки Java с java.com/download вполне достаточно для работы приложения. Для себя выявил два возможных пути удобного распространения приложения: если не вынуждать пользователя устанавливать Java, можно чтобы один раз он скачал папку с jre (путь до которой указывается, например, при создании exe из jar с помощью launch4j; либо можно предоставить пользователю папку с jre и запускать jar файл с помощью jre/bin/java -jar app.jar - спасибо за наводку товарищу Regent), и, впоследствии, чтобы обновлять программу у пользователя, можно просто предоставлять ему jar или exe файл, чтобы он помещал его с заменой в бывшую директорию приложения. Если же у пользователя установлена Java, нет никакой необходимости в дополнительном предоставлении чего-либо, достаточно исполняемого файла. Конкретно по моей проблеме: javaw.exe запускался лишь на секунду, потому что программа работала с ошибкой (в коде я указал абсолютный путь до иконки программы, и поэтому была самая тривиальная ошибка Can't read input file, но у меня на компьютере проблем, естественно, не было; Спасибо товарищу Regent, натолкнул на мысль о возможной ошибке).

перезапись свойст объекта JavaScript

//соханим начальные настройки var def = Object.assign({}, this.curSet); // выберем все брейкпоинты из настроек var query = []; for (var key in def.media) { query.push(def.media[key].point); } // фукция устанавливает настройки для запуска function setNewSettigs(mql) { var newSet = Object.assign({}, def); for (var key in newSet.media) { for (var prop in newSet.media[key]) { if (newSet.media[key][prop] == mql.media) { // вот здесь в IE10+ всегда false for (var set in newSet.media[key].settings) { if (set in newSet) { newSet[set] = newSet.media[key].settings[set]; } } } } } return newSet; } // функция производит действия при совпадении медиа выражения function run(mql) { if (mql.matches) { this.curSet = Object.assign({}, setNewSettigs(mql)); console.log(this.curSet) this.start(); console.log(mql.media) } else { this.curSet = Object.assign({}, def); this.start(); } } // создадим медиа запросы и повесим обработчики на них query.forEach(function(item, i, arr) { var mql = window.matchMedia(arr[i]); mql.addListener(run.bind(this)); run.call(this, mql); }, this);
Добрый день, под спойлером код, с помощью которого я хочу перезапускать инициализацию объекта с новыми параметрами ориентируясь на медиа запросы, используя machmedia. Выглядит создание объекта следующим образом:
var obj = new Obj({ elem: document.querySelector('.CSSClass'), count: 4, // это объект с контрольными точками и свойствами которые нужно перезаписать media: { point1: { // контрольная точка point: 'only screen and (max-width: 768px)', // перезаписываемые свойства settings: { count: 3, } }, point2: { point: 'only screen and (max-width: 480px)', settings: { count: 1, } }, } });
И казалось бы все прекрасно работает(за исключением одного нюанса, о нем ниже), но стоило открыть мне IE и увы.... Функция setNewSettigs из кода под спойлером не перезаписывает параметры настроечного объекта на значения из settigs кода выше, причем 9-ка отрабатывает нормально, а вот уже начиная с 10-ки такой казус. Вопрос: Почему так происходит. Кто поможет разобраться?
P.s. А теперь про нюанс о котором выше. в настройках 2 контрольные токи, на 768рх и 480рх. Параметр count - отвечает за количество отображаемых блоков в текущем экране. Так вот, когда идет уменьшение экрана все хорошо на 768 отображается 3 блока, на 480 1, но вот когда начинаешь увеличивать окно снова после 480, казалось бы нужно после прохождения порога в 481 отображать 3 блока, так это вписывается в диапазон 768. Но в скрипте стоит запуск с исходными настройками если нет совпадений медиазапросе, как можно сделать так, что бы скрипт запоминал что между выставленными контрольными точками должны применяться настройки большего экрана?
Обновление вопроса.
Потестив код, выяснилось, что не срабатывает условие newSet.media[key][prop] === mql.media и при переборе свойств выражение всегда возвращает false, в следствии чего и не перезаписываются свойства.... Почему себя так ведут иешки 10+ ? Баг или как же правильно сделать? Для чего нужно это сравнение - когда идет обход объектов внутри параметра media в настройках, сраниваются значение его свойств со значением mql.media который пришел в функцию и если есть совпадение идет перезаписывание свойств из settings, того объекта в котором было совпадение. mql - это экземпляр window.matchmedia, он создается в цикле по query (последний цикл в коде под спойлером). У него есть свойство media, в котором храниться строка медиа запроса. newSet.media[key][prop] - здесь проход по свойствам объекта media, которые в свою очередь так же объекты в которых есть свойство point - так же строка для медиа запроса. Так вот как раз и проверяется на совпадение строки из mql.media со строкой из newSet.media[key].point


Ответ

Оказалось при задании настроек я писал:
media: { point1: { point: 'only screen and (max-width: 768px)', settings: { count: 3, } }, point2: { point: 'only screen and (max-width: 480px)', settings: { count: 1, } }, }
При создании экземпляра window.matchmedia в его свойство media попадало: 'only screen and (max-width:480px)'. Т.е. между двоеточием и значением нету пробела. Поэтому - то иешки и говорили что они не равны..... Причем этот пробел убирают только иешки 10+
'only screen and (max-width: 768px)' == 'only screen and (max-width:768px)' // false

Ограничение времени выполнения метода в основном потоке

Есть некоторая проблема - работаю с одним API примерно следующим образом:
событие -> запрос от их API к моему серверу -> [какие-то действия -> мой запрос к их API (или несколько)] -> на основе их ответа уже мой ответ их запросу
Так вот, действия, происходящие в [квадратных скобках] могут выполняться очень долго (как ни странно, в виду долгого их ответа, а не моего). Несмотря на это, после 20 или 25 секунд, примерно, их сервер перестаёт ждать моего ответа.
Что мне нужно сделать:
событие -> запрос от их API к моему серверу -> я запускаю обработку запроса, которая должна длиться не более 20 секунд, если дольше - возвращаю дефолтный ответ -> [какие-то действия -> мой запрос к их API (или несколько)] -> на основе их ответа уже мой ответ их запросу
То есть нужно сделать так, чтобы при превышении времени обработки, я давал дефолтный ответ. Я не хочу уменьшать сам время ожидания, и так далее, мне нужно сделать именно так, как я описал, не меняя ничего остального в коде.
Я могу всю свою обработку сунуть в переопределённый run() нового потока, и заjoin()ить его, и как в этом примере, интерраптить через определенное количество секунд. Но это крайне небезопасно, и всё такое прочее. К тому же, во время выполнения, я и к базе данных обращаюсь, и сам запросы какие-то делаю.
Буду рад, если подскажете возможное решение.

Немного конкретики, если вдруг кто решит уточнить:
Работаю с VK Callback API, во время обработки их запросов, появляется необходимость скачать аватар пользователя или ещё некоторые файлы. То есть, я обращаюсь к файлу по URL и скачиваю его на диск следующим образом (не спрашивайте, почему так, а не с использованием библиотек апачей):
public void downloadFile(String fileURL, String saveFilePath) { try { int BUFFER_SIZE = 4096; URL url = new URL(fileURL); HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); int responseCode = httpConn.getResponseCode();
// always check HTTP response code first if (responseCode == HttpURLConnection.HTTP_OK) {
// opens input stream from the HTTP connection InputStream inputStream = httpConn.getInputStream();
// opens an output stream to save into file FileOutputStream outputStream = new FileOutputStream(saveFilePath);
int bytesRead; byte[] buffer = new byte[BUFFER_SIZE]; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); }
outputStream.close(); inputStream.close(); } httpConn.disconnect(); } catch (IOException e) { e.printStackTrace(); } }
Или же просто считываю картинку с URL:
BufferedImage img = ImageIO.read(new URL("https://..."));
И постоянно ошибки, либо такая (ссылается на строчку, приведенную чуть выше):
javax.imageio.IIOException: Can't get input stream from URL! at javax.imageio.ImageIO.read(ImageIO.java:1395)
Либо такая:
java.net.ConnectException: Connection timed out (Connection timed out)
Которая ссылается на эту строчку:
int responseCode = httpConn.getResponseCode();
Такое случается не всегда, и только последнее время, + было еще чуть больше недели назад. Но сейчас уже два дня подряд, причем постоянно, и с этим надо как-то бороться. Пробовал добавлять User-Agent, вдруг в этом проблема, но это тоже не помогает. Да и вычислить, помогает это или нет, довольно трудно, потому что эта ошибка выскакивает когда хочет, и приходится повторять действия неоднократно, чтобы понять, решена проблема или нет.


Ответ

Поскольку на первый вопрос мне изначально не ответили, я решил его переформулировать и задать этот вопрос. Отвечаю на вторую часть своего вопроса: мне нужно было сделать так, чтобы клиент не ждал окончания выполнения всех моих действий. На этот вопрос я ответил тут: Порядок выполнения содержимого методов doPost и doGet

Для чего нужен отрицательный margin и положительный padding в bootstrap?

Bootstrap'ом редко пользовался, как-то не вникал в эти положительные и отрицательные отступы блоков.
Подскажите, для чего в блоке .container положительный padding, а в блоке .row отрицательный margin? Какая практическая польза в этих отступах?


Ответ

Это сделано для выравнивания.
У каждой колонки слева и справа есть padding, равный 15px. Он нужен для генерации одинакового отступа между колонками. Однако в этом случае отступ слева у первой и отступ справа у последней колонки в строке складывается с отступами контейнера.
Чтобы нивелировать его используется .row с отрицательным margin равным 15px. Если использовать .row, то левый отступ у первого столбца и правый отступ у правого столбца "проваливаются" в уже существующие отступы у контейнера и не занимают дополнительного места.
На вопрос почему бы не убрать отступ у контейнера и отказаться от отрицательного margin у .row ответ простой: блоков с контейнером может быть несколько, и в одном из них может отсутствовать сетка.
Чтобы блоки с сеткой и без нее были выравнены по левой и правой границе, как раз и придумали этот прием с отрицательными margin. А сам padding у контейнера еще нужен и для того, чтобы его содержимое не прилипало к границе экрана на небольших разрешениях.
update: при многократной вложенности, в качестве контейнера выступает уже колонка, а принцип действия тот же самый.

Передача объектов в игре между классами

Я пишу небольшую игру на JavaScript (ES6). Есть в игре объекты, такие как Camera, Scene и тд, к которым очень часто нужен доступ. Сначала я делал так:
Есть объект Game, в нем есть gameProto.camera = new Camera(this), gamepProto.scene = new Scene(this) и везде передавал объект игры, абсолютно везде. Объект Game передавался почти во все конструкторы, где мне нужен был доступ к сцене и камере.
Не так давно я разобрал Swift и мне очень понравились "общие" объекты. Например NSApplication.Shared() - вероятно, это синглтон. Подумал я и решил сделать также. Camera.Shared - стал статичный объект общей камеры. Scene.Main - стал статичный объект главной сцены (а она одна на всю игру, как и камера). Теперь я перестал передавать во все конструкторы объект игры и стал использовать "общие" объекты, сделав игру модульной.
В чем собственно сам вопрос? В смысле оптимизации - как же лучше передавать объекты: ссылками в конструкторы или использовать "общий" статичный объект? А может и нет разницы вообще?


Ответ

Добрый день! Постараюсь ответить на ваш вопрос, хотя это немного сложно поскольку он очень общий 🙂
Следуйте рекомендациям создателей движка на котором вы пишите игру. Обычно эти советы базируются на конкретной реализации внутренних механизмов вашего движка. Если уж совсем нет рекомендаций можно посмотреть что делают другие люди на этом же движке. Используйте здравый смысл. Зачастую, если есть несколько вариантов как реализовать ту или иную функциональность и разница в производительности этих вариантов незначительна, то мой вам совет - выбирайте ту которая проще. Не нужно делать сложно то что, возможно, никогда вам больше не потребуется. Отсюда следующее. Концентрируетесь на готовом продукте. Почему? Потому что я видел миллионы мертвых проектов (включая мои собственные) в которых разработчики пытались всё заоптимизировать до смерти и эти проекты не доживали до релиза. Прошу заметить: я не призываю вас писать низкосортный код, я предлагаю сосредоточится на результате. А вот когда у вас уже есть готовый продукт, тогда уже можно его оптимизировать. Относитесь взвешенно к советам от "гуру" и "экспертов", иногда они только мешают. "Тебе обязательно нужно TDD а также DI для IoC и если у тебя нет CI то ты просто вообще непонятно как живешь!" Оно конечно всё очень хорошо, но пожалуй только если у тебя команда из как минимум пяти человек, ну а если нет - можно и без этого, поверьте на слово 🙂 Если хотите более мудрое описание в виде притчи - оно ниже ПРИТЧИ: Отец, сын и осёл Как-то раз отец со своим сыном и ослом в полуденную жару путешествовали по улицам города. Отец сидел верхом на осле, а сын вёл его за уздечку. — Бедный мальчик, — сказал прохожий, — его маленькие ножки едва поспевают за ослом. Как ты можешь лениво восседать на осле, когда видишь, что мальчишка совсем выбился из сил? Отец принял его слова близко к сердцу. Когда они завернули за угол, он слез с осла и велел сыну сесть на него. Очень скоро повстречался им другой человек и сказал: — Как не стыдно! Малый сидит верхом на ослике, как султан, а его бедный старый отец бежит следом. Мальчик очень огорчился от этих слов и попросил отца сесть на ослика позади него. — Люди добрые, видали вы где-либо подобное? — заголосила женщина под чадрой. — Так мучить животное! У бедного ослика уже провис хребет чуть ли не до земли, а старый и молодой бездельники восседают на нём, будто он диван, о несчастное животное! Не говоря ни слова, отец и сын, посрамлённые, слезли с осла. Едва они сделали несколько шагов, как встретившийся им человек стал насмехаться над ними: — Чего это ваш осёл ничего не делает, не приносит никакой пользы и даже не везёт кого-нибудь из вас на себе? Отец сунул ослику полную пригоршню соломы и положил руку на плечо сына. — Что бы мы ни делали, — сказал он, — обязательно найдётся кто-то, кто с нами будет не согласен. Я думаю, мы сами должны решать, как нам путешествовать. Иной раз полезней, не слушая чужих советов, следовать своим путем по своему плану. Ведь свою жизнь проживаем мы, а не посторонние советчики.
Помните, лучше готовая игра в которой есть куски кода которые на ночь лучше не смотреть 🙂 чем красивые исходники этой неработающей игры
Итого мне кажется в javascript'е нет никакой проблемы в "общем" статичном объекте. На мой взгляд это удобнее чем передавать миллион параметров. Если я не ошибаюсь именно так работает phaser.io .

Из Array в псевдомассив

Многие спрашивают, как NodeList, HTMLColletion и другой псевдомассив превратить в Array. Так мне нужно наоборот. То есть мне нужно превратить Array, к примеру, в NodeList.
Как это сделать?
Есть два "но":
Я не знаю что у меня именно: NodeList, HTMLColletion или какой-то другой псевдомассив; но у меня есть псевдомассив с тем прото, в который нужно превратить массив. Варианты с изменением через параметр __proto__ не предлагать, так как мне нужен вариант, который сработает, как минимум, в IE10


Ответ

К сожалению, искусственно создать псевдомассив (массивоподобный объект), вроде NodeList и HTMLCollection, никак нельзя, даже с помощью свойства __proto__
Когда вы измените __proto__ массива, то он просто изменит "родителя" с Array на другой, который вы укажите при смене. Тем самым изменить стандартные свойства с Array.prototype на [{Object}].prototype
var elements = document.querySelectorAll('div'); var array = [document.querySelector('div')]; // Изменяем прото массива array.__proto__ = NodeList.prototype; // Проверяем содержимое обоих элементов console.log(elements); // [

, item, entries, forEach, keys, values] console.log(array); // [
, item, entries, forEach, keys, values] // Провряем тип элементов console.log({}.toString.call(elements)); // [object NodeList] console.log({}.toString.call(array)); // [object NodeList] // Но тут сюрприз console.log(Array.isArray(elements)); // false console.log(Array.isArray(array)); // true

Как видно из примера, массив не перестал быть массивом, но чисто визуально и по типу объекта он выглядит, как NodeList.
Технически, псевдомассивом может быть любой объект, у которого внутри есть свойство length, которое должно быть целым положительным числом. По крайней мере, Array.from() обращает внимание в основном на это свойство.
Object.canAccessAsArray = function(object) { return Number.isInteger(Number(object.length)) && Number(object.length) >= 0; }; // Тут выдаст массив с тремя пустыми значениями console.log( Object.canAccessAsArray({length: 3}) + ' => ' + Array.from({length: 3}) ); // А тут есть значения console.log( Object.canAccessAsArray({'0': 'a', '1': 'b', '2': 'c', length: 3}) + ' => ' + Array.from({'0': 'a', '1': 'b', '2': 'c', length: 3}) ); // А тут будет пустой массив, из за отсутствия length console.log( Object.canAccessAsArray({'0': 'a', '1': 'b', '2': 'c'}) + ' => ' + Array.from({'0': 'a', '1': 'b', '2': 'c'}) );

Ошибка при вызове метода $('#id').load()

Доброго времени суток.
Бэк: ASP.NET Core 1.1.
В данном действии происходит только подготовка запроса к отправке
При загрузке в элемент данных с помощью $('#id').load() возникает ошибка:
Uncaught TypeError: Cannot read property '*' of undefined
Версия, которая работала месяц назад, тоже не работает(сделал откат, тогда работала).
Прошерстив место возникновения ошибка(jQuery метод, у них в библиотеки), узнал что при отправке запроса на сервер dataTypes="*"
Вот кусок кода из библиотеки JQuery(не моя), где происходит ошибка:
// Set the Accepts header for the server, depending on the dataType jqXHR.setRequestHeader( "Accept", s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? s.accepts[ s.dataTypes[ 0 ] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : s.accepts[ "*" ] );
Попробовал использовать $.ajax, чтобы явно указать dataType:
$.ajax(url, { accepts: 'application/json; charset=utf-8', dataType: 'json',method: 'GET' });
dataType = '*' также, но ошибка уже возникает на строке с вызовом
// Uppercase the type s.type = s.type.toUpperCase();
Где происходит повышение в регистр типа запроса. Явно это указал в ajax и эта часть работает корректно, но ошибка теперь та же(просто это строка идет перед той, где происходит проверка на *).
Подскажите, куда копать. Эта часть не трогалась месяц.
Update 1:
Cкрин объекта s

Update 2
Код на интерфейсе программы, на котором возникает ошибка.
Переменные передаются нормально. Напомню, что я уже откатился на месяц назад, когда все идеально работало и эта ошибка там тоже присутствует.
$('#details').load("/Drive/EditDelete?M2Mid=" + M2Mid);


Ответ

Из-за накопления количества глупых ошибок мы ушли с платформы ASP.NET Core и вэба вообще(возможно мы просто не умеем в вэб)
Поэтому ответ на вопрос остался тайной, покрытой дымкой неизбежного мрака.

Как правильно использовать GitLab.com?

Выбрали для совместной деятельности GitLab.com, но это первый наш опыт совместного ведения проекта. Как грамотней использовать GitLab.com: с одним общим аккаунтом или создавать для каждого свой?
У нас сейчас вариант 1, но хотим уточнить, правильно ли мы понимаем вариант 2. Может есть ещё варианты?


Ответ

Я тоже работаю с GitLab. Мы сделали один аккаунт, чисто для хранения наших проектов. Естественно, закрытый. Каждый отдельный разработчик создает свой аккаунт отдельно. Затем, кто-то из вас расшаривает доступ к главному аккаунту(где лежит ваш проект) для всех разработчиков. Вы создаете свои дочерние ветки, куда вносите свои изменения, а потом кто-то заливает их в главную. Вот и все, собственно. Не говорю, что это правильно, но мы так работаем.