Страницы

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

четверг, 30 мая 2019 г.

В чем преимущества выделения контроллера в mvc?

У меня сразу несколько вопросов по mvc. Спрашивать буду на примере игрушечной программки, которую специально для этого написал:
public class View implements Observer {
private Model model; private IController controller;
private JLabel firstNumber = new JLabel(); private JLabel secondNumber = new JLabel(); private JLabel resultLabel = new JLabel();
public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { Model model = new Model(); IController controller = new Controller(); View view = new View(); view.setModel(model); view.setController(controller); view.createAndShowGUI(); } }); }
public void setModel(Model model) { this.model = model; model.addObserver(this); }
public void setController(IController controller) { this.controller = controller; }
public void createAndShowGUI() { JFrame frame = new JFrame("mvc train"); frame.setSize(400, 400); frame.getContentPane().add(createMainPanel()); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }
private Component createMainPanel() { JPanel mainPanel = new JPanel(); mainPanel.add(firstNumber); mainPanel.add(secondNumber); mainPanel.add(resultLabel); JButton inc1 = new JButton("increment first"); inc1.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) { controller.execute("inc1", model); } }); JButton dec1 = new JButton("decrement first"); dec1.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) { controller.execute("dec1", model); } }); mainPanel.add(inc1); mainPanel.add(dec1); JButton inc2 = new JButton("increment second"); inc2.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) { controller.execute("inc2", model); } }); JButton dec2 = new JButton("decrement second"); dec2.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) { controller.execute("dec2", model); } }); mainPanel.add(inc2); mainPanel.add(dec2); return mainPanel; }
@Override public void update(Observable arg0, Object arg1) { firstNumber.setText("" + model.getA()); secondNumber.setText("" + model.getB()); resultLabel.setText("" + (model.getA() + model.getB())); }
}
Это класс представления. Получается такая картинка:
Кнопка increment first увеличивает на единицу первое число, increment second - второе, decrement first уменьшает первое число на единицу, decrement secomd - второе. В общем, после двух нажатий на increment first и одного нажатия на increment second получаем такую картинку:

Два числа хранятся в модели. Вот она:
public class Model extends Observable {
private int a; private int b;
public void incrementA() { a++; setChanged(); notifyObservers(); }
public void incrementB() { b++; setChanged(); notifyObservers(); }
public void decrementA() { a--; setChanged(); notifyObservers(); }
public void decrementB() { b--; setChanged(); notifyObservers(); }
public int getA() { return a; }
public int getB() { return b; }
@Override public void addObserver(Observer observer) { super.addObserver(observer); setChanged(); notifyObservers(); }
}
Мой контроллер:
public class Controller implements IController {
@Override public void execute(String action, Model model) { switch (action) { case "inc1": model.incrementA(); break; case "inc2": model.incrementB(); break; case "dec1": model.decrementA(); break; case "dec2": model.decrementB(); } }
}
Теперь вопросы. Самый главный вопрос собственно в названии.
Чем нам помог контроллер? Код из веток case оператора switch в контроллере мог бы с таким же успехом находится в слушателях. На каждую ветку по слушателю. В итоге слушателей все равно приходится создавать, что бы вызвать метод контроллера. А потом в этом методе в операторе switch прописывать тот же самой код, что мог бы быть в слушателях. Может быть я вообще неправильно реализовал mvc? Подозреваю что именно так. Причем именно в части контроллера. Потому что по нему в сети мало информации. Если это так то прошу подсказать как правильно. Слышал что можно создавать контроллеры для каждого элемента (в данном случае для каждой кнопки). Но ситуация не сильно поменяется. В моем примере все методы, которые вызывается в ветках case не имеют параметров. В реальных программах это скорее всего будет не так. Некоторые кнопки могли бы требовать вызовов методов с параметрами, причем с разным количеством параметров. Что делать в такой ситуации? Где лучше вычислять самое правое число? В моем примере я делаю это в функции update(). Не лучше ли это делать в модели?


Ответ

Контроллер помогает структурировать код. Весь код, реагирующий на пользовательский ввод, принадлежит контроллеру.
Можно было бы всё слить в один класс, и делать всю логику в OnClick, и код получился бы наверное даже короче. Но вашей целью должен быть не самый короткий, а самый понятный и легко поддерживаемый код. Мне кажется, ваша диспетчеризация команд по строкам — неправильна. Команды должны быть не строками, а объектами. (У нас же ООП, в конце-концов, да?) И вместо длинного свитча у вас должен быть всего лишь вызов Invoke. [Но это практика из MVVM, общепринятого паттерна в WPF, а традиции в MVC могут быть и другими.] Вычисления принадлежат модели и только ей. Представление должно не выполнять работу модели (а сложение в реальной программе превратится в серьёзное, длинное вычисление), а лишь только отображать её.

Поиск всех значений в TreeMap c “неполным” ключом

Доброго времени суток. Нужен совет, как найти все значения в TreeMap с "неполным" ключом. Допустим имеются какие то значения с ключами "Book","Boom","Trap"... При ключе "Boo" должен выводить значения у которых ключ начинается на этот кусок.
Пробовал использовать методы ceilingKey(), floorKey(), higherKey(), lowerKey(), но столкнулся с проблемой, выводит лишь одно значение. Попробовал удалять элементы после получения, тогда он выводит весь TreeMap пока не опустеет.
Может есть какой то более подходящий подход для этой задачи ?


Ответ

На англоязычном SO есть несколько таких вопросов с ответом
Идея такая: используем метод subMap, первым параметром передаем наш префикс (или как вы говорите "неполный ключ"), вторым параметром передаем этот же неполный ключ, только с измененным последним символом, который на единицу больше предыдущего (либо можно просто в конец "неполного ключа" дописать Character.MAX_VALUE).

Узнать имя класса во время исполнения программы

У меня есть функция (используется для записи логов), которая вызывается в разных классах. Не хочется каждый раз переписывать код в ней для каждого нового класса(они будут и добавляться и убираться со временем, ну или вообще функция будет использоваться в дальнейшем в других проектах).
Мне хотелось бы узнавать имя класса, из которого она вызывается (для задания имени файлу и прочих плюшек) не передавая лишних параметров в функцию.
Это можно реализовать? Можно и boost`ом.


Ответ

Функция typeid(object) возвращает объект типа type_info с информацией о типе объекта, для которого она вызывается (собственно, о классе). У этого объекта(type_info) есть метод name(), который и возвращает имя класса. Для использования нужно подключить
Так что в итоге для получения имени класса нужно использовать
typeid(*this).name()
Или, если функция не является методом класса, передать в typeid сам объект или разыменованный указатель.

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

Дано: бинарное дерево (алгоритм дерева написан вручную). Число S. Нужно найти последовательность узлов (только с вверху вниз или наоборот) в бинарном дереве, сумма которых равна S
Например: есть бинарное дерево, а число S = 9.
Решение: 3+6, 4+5, 9.
п.с. желательно, что бы это был отдельный класс, который имел доступ к классу binTree
#pragma once class binTree { protected: struct Node { int Value; Node * pLeft; Node * pRight; Node * pParent; Node(int x) :Value(x), pLeft(NULL), pRight(NULL), pParent(NULL) {} }; Node * m_pRoot; void InoderTreeWalk(Node * x); Node * TreeSuccessor(Node *x); Node * TreeMin(Node * x); public: binTree(); ~binTree(); virtual void TreeInsert(int k); Node * TreeSearch(Node * X, int k); void ShowTree(); int Root(); };


Ответ

Задача тянет на олимпиадную, пишу идею.
Решение будет сделано с помощью динамики по дереву.
Для каждого узла в дереве заведём список значений. Инициализация - в листах {0, Value}. Пересчёт снизу вверху. Значение для узла пересчитывается примерно так (текущая вершина U):
for (auto left : U->left->list) U->list.add(left + U->Value); for (auto right: U->left->right) U->list.add(right+ U->Value); U->add(U->Value); U->list->unique();
Я специально пишу псевдокодом, т.к. там может быть любая структура от специфики задачи (list vector set bitset) и т.д.
Для каждой вершины, где в списке есть S будет последовательность ответ, которая заканчивается в ней. Её можно восстановить примерно так. Последовательность однозначно задаётся начальным и конченым элементом. Я верну только начальные.
list fun(Tree *U, int S){ S -= U->Value;
list tmp; if (S == 0) tmp.add(U);
if (U->left->list.contains(S)) tmp.add(fun(U->left,S); if (U->rigth->list.contains(S)) tmp.add(fun(U->rigth,S); return tmp; }
Сложно что-то порядка O(N^2 log N). Оптимизировать можно, но если выводить все последовательности то их может быть примерно столько же. Дальнейшие реализации/оптимизации вам виднее.

Entity Framework не удаляется связанная по внешнему ключу запись

Пытаюсь удалить элемент из коллекции UsersVaults объекта типа User, но получаю Exception (текст ошибки и код ниже). Подскажите, где я повернул не туда?
Метод изменения объекта:
[HttpPost] public ActionResult Edit(int id, FormCollection form) { try { using (var db = new AccessControlSystemDatabaseModel()) { var user = db.Users.Find(id); var tempData = form.AllKeys.ToDictionary(key => key, key => form[key]);
user.RoleID = Convert.ToInt32(tempData["RoleID"]); user.Username = tempData["Username"].ToString(); user.Password = tempData["Password"].ToString(); user.Email = tempData["Email"].ToString();
if (!tempData["GrantAccess"].ToString().Equals("false") && user.UsersVaults.Where( d => d.VaultID == AuthenticationController.CurrentUser.UsersVaults.ToList()[0].VaultID) .ToList() .Count == 0) { user.UsersVaults.Add(new UsersVault { UserID = id, VaultID = AuthenticationController.CurrentUser.UsersVaults.ToList()[0].VaultID, }); } else { var tt = user.UsersVaults.Where( d => d.VaultID == AuthenticationController.CurrentUser.UsersVaults.ToList()[0].VaultID).ToList()[0];
user.UsersVaults.Remove(tt); }
db.Entry(user).State = EntityState.Modified; db.SaveChanges();
return RedirectToAction("Index"); } } catch(Exception e) { return RedirectToAction("Index"); } }
Модель:
public partial class AccessControlSystemDatabaseModel : DbContext { public AccessControlSystemDatabaseModel() : base("name=AccessControlSystemDatabaseModel") { }
public virtual DbSet Roles { get; set; } public virtual DbSet Users { get; set; } public virtual DbSet UsersVaults { get; set; } public virtual DbSet Vaults { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity() .HasMany(e => e.UsersVaults) .WithRequired(e => e.User) .WillCascadeOnDelete(true);
modelBuilder.Entity() .HasMany(e => e.UsersVaults) .WithRequired(e => e.Vault) .WillCascadeOnDelete(true); } }
public partial class Role { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] public Role() { Users = new HashSet(); }
public int ID { get; set; }
[Required] [StringLength(255)] public string RoleName { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] public virtual ICollection Users { get; set; } }
public partial class User { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] public User() { UsersVaults = new HashSet(); }
public int ID { get; set; }
[Required] [StringLength(255)] public string Username { get; set; }
[Required] [StringLength(255)] public string Password { get; set; }
public int? RoleID { get; set; }
[StringLength(255)] public string Email { get; set; }
public virtual Role Role { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] public virtual ICollection UsersVaults { get; set; } }
public partial class UsersVault { public int ID { get; set; }
public int UserID { get; set; }
public int VaultID { get; set; }
public virtual User User { get; set; }
public virtual Vault Vault { get; set; } }
public partial class Vault { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] public Vault() { UsersVaults = new HashSet(); }
public int ID { get; set; }
[Required] [StringLength(255)] public string VaultName { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] public virtual ICollection UsersVaults { get; set; } }

Текст исключения:
"Операция завершилась с ошибкой. Не удалось изменить связь, поскольку один или несколько свойств внешнего ключа не допускают значения NULL. При изменении связи соответствующему свойству внешнего ключа присваивается значение NULL. Если внешний ключ не поддерживает значений NULL, должна быть определена новая связь, свойству внешнего ключа должно быть присвоено другое значение, отличное от NULL, либо необходимо удалить несвязанный объект."


Ответ

В EF, к сожалению, операции Add и Remove для навигационных коллекций не всегда симметричны - первая операция устанавливает связь между сущностями и при необходимости добавляет их в базу, вторая же только разрывает связь. Но разорвать связь между UsersVault и User невозможно, отсюда и ошибка.
Поэтому надо вместо удаления объекта из коллекции явно удалить его из базы:
var tt = user.UsersVaults.Single(...); db.Entry(tt).State = EntityState.Deleted;
или
db.UsersVaults.Remove(tt);
Для сохранения симметричности операций, можно при добавлении UsersVault точно так же сразу добавлять его в базу:
db.UsersVaults.Add(new UsersVault { UserID = id, VaultID = ..., })
Кстати, в вашем текущем коде есть дублирование - UserID присваивать не обязательно если вы добавляете объект через навигационную коллекцию - EF проставит его сама.

В качестве альтернативного решения могу предложить вообще удалить сущность UsersVault - она не нужна! EF умеет самостоятельно отображать связи "многие-ко-многим" на промежуточные таблицы, просто создайте mtm-связь между Users и Vaults

Как работать с TCP в Swift?

У меня есть TCP сервер, который слушает входящие команды и общается с БД. Как мне слать к нему запросы из ios приложения? Работаю со swift 2
Другими словами, нужно реализовать следующее: Пользователь вводит логин и пароль, пытается войти в свой аккаунт. В это время посылается запрос на сервер - "Проверь, есть ли такой юзер в БД". Он это делает, и шлет ответ обратно на ios приложение.
Никак не могу понять, как мне такое реализовать. Насколько я понимаю, мне нужно работать с потоками, но ничего путного про это на ios я не нашел.


Ответ

Если я Вас правильно понял, то потоки Вам вовсе не нужны. Тут надо использовать блоки. Скажем Вы отправляете запрос и включаете индикатор загрузки, а когда приходит ответ Вы прекращаете загрузку и в зависимости от результата с сервера используете success или же failure блок. Советую использовать AFNetworking
Что-то на подобии
let manager = AFHTTPRequestOperationManager() manager.GET( "http://myServerUrl.com", parameters: ["email":"myemail@gmail.com", "password":"1234Password"], success: { (operation: AFHTTPRequestOperation!, responseObject: AnyObject!) in //TODO - make login action }, failure: { (operation: AFHTTPRequestOperation!, error: NSError!) in // TODO - show error message } )

Как добавить в приложение уже заполненную базу?

Есть приложение, в нем есть список чего-то на 200 итемов.
Как мне поставлять приложение с уже заполненной базой ? т.е. чтобы после установки приложения этот список заполнился из базы.


Ответ

Схематично:
В assets кладете Вашу БД Создаете БД в приложении (стандартно SQLiteOpenHelper) Копируете при первом запуске БД из assets в БД приложения. Работаете с заполненной БД. После очистки данных приложения пользователем повторить п.3

Как передать результат выполнения асинхронного запроса обратно в вызвавшую его активность?

Есть окно с элементом spinner, который должен заполняться значениями из базы данных MS SQL. Для связи с БД использую jtds 1.2.8 в асинхронных запросах, но никак не выходит найти способ чтобы переправить данные результата запроса в активность, которая послала асинхронный запрос. Как реализовать заполнение spinner после выполнения запроса?
UA.java
public class UA extends AppCompatActivity{
private QueryItem Item = new QueryItem();
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_ua); Item.setId(Search_Page.id_intent); Search_Page.id_intent = 0; String[] query = new String[2]; query[1] = "get_dish_links"; query[0] = "EXEC " + query[1] + "" + Item.getId(); new AsyncRequest().execute(query); final SeekBar seekbar = (SeekBar) findViewById(R.id.seekBar); }
public void onClick(View view) { final Spinner spinner = (Spinner)findViewById(R.id.spinner); //Item.setUnit(spinner); }
public void fill_spinner(List links){ final Spinner spinner = (Spinner)findViewById(R.id.spinner); ArrayAdapter possible_units = new ArrayAdapter(this, android.R.layout.simple_list_item_1, links); spinner.setAdapter(possible_units); spinner.setSelection(0); possible_units.notifyDataSetChanged(); }
AsyncRequest.java
public final class AsyncRequest extends AsyncTask {
public final static String MSSQL_DB = "jdbc:jtds:sqlserver://localhost:1433; DatabaseName=Lazycook"; public final static String MSSQL_LOGIN = "lazyuser"; public final static String MSSQL_PASS = "12344321"; public final static JSONConverter conv = new JSONConverter(); public String action;
@Override protected JSONArray doInBackground(String[] query) { JSONArray resultSet = new JSONArray(); action = query[1]; try { Class.forName("net.sourceforge.jtds.jdbc.Driver"); Connection con = null; Statement st = null; ResultSet rs = null; try { con = DriverManager.getConnection(MSSQL_DB, MSSQL_LOGIN, MSSQL_PASS); if (con != null) { st = con.createStatement(); rs = st.executeQuery(query[0]); if (rs != null) { int columnCount = rs.getMetaData().getColumnCount(); // Сохранение данных в JSONArray while (rs.next()) { JSONObject rowObject = new JSONObject(); for (int i = 1; i <= columnCount; i++) { rowObject.put(rs.getMetaData().getColumnName(i), (rs.getString(i) != null) ? rs.getString(i) : ""); } resultSet.put(rowObject); } } } } catch (SQLException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } finally { try { if (rs != null) rs.close(); if (st != null) st.close(); if (con != null) con.close(); } catch (SQLException e) { throw new RuntimeException(e.getMessage()); } } } catch (ClassNotFoundException e) { e.printStackTrace(); } return resultSet; }
@Override protected void onPostExecute(JSONArray result) { switch (action){ case "get_dish_links" : { List links = conv.JSONtoLink(result); // вот здесь думал использовать вызов fill_spinner // нужного объекта, передав ему результат }
} }
}


Ответ

Создайте интерфейс
public interface MyInterface { void doSmth(JSONArray result); } Реализуйте его в активити
public class UA extends AppCompatActivity implements MyInterface{
@Override public void doSmth(JSONArray result) { System.out.println("вызван doSmth в Активити"); //вот и ваш результат из задачи в актвити }
... } Передавайте его в задачу через конструктор и вызывайте его метод, передавая туда результат из onPostExecute
public final class AsyncRequest extends AsyncTask {
MyInterface myInterface;
public AsyncRequest(MyInterface myInterface){ this.myInterface = myInterface; }
@Override protected void onPostExecute(JSONArray result) { System.out.println("вызван onPostExecute"); myInterface.doSmth(result); } } В активити запускайте так:
new AsyncRequest(UA.this).execute(query);

Python. Вывод текста по середине терминала

Как можно вывести текст в центре экрана терминала, используя shutil.get_terminal_size().columns и shutil.get_terminal_size().lines?


Ответ

Если текст уже разбит на строки, то достаточно просто отформатировать:
>>> import shutil >>> lines = ['String right here', 'And here', 'Here', 'A-a-a-and here'] >>> width = shutil.get_terminal_size().columns >>> position = (width - max(map(len, lines))) // 2 >>> for line in lines: # left justtified ... print(' '*position + line) ... String right here And here Here A-a-a-and here >>> for line in lines: # right justified ... print(line.rjust(width // 2)) ... String right here And here Here A-a-a-and here >>> for line in lines: # center ... print(line.center(width)) ... String right here And here Here A-a-a-and here

Шаблонная хэш-функция

Допустим, мне нужно сделать некий шаблонный контейнер Map на хэш-таблице. Контейнер, естественно, может принимать ключем значение любых типов - как, в таком случае, написать хэш-функцию? Как привести произвольный тип T (для которого может быть не перегружен оператор приведения) к целочисленному типу? Вроде как должен помочь reinterpret_cast, который приводит к указателю, но конструкция вида
reinterpret_cast (key);
Отказывается компилироваться, когда key имеет не-целочисленный тип.
Если же приводить указатель к указателю (как в примере на msdn)
reinterpret_cast (&key);
то теряется смысл хэш таблицы - поиск по ней не будет работать, поскольку ключ с идентичным значением будет иметь другой адрес, и результат хэш-функции будет тоже другой.
Можно ли как-то насильно интерпретировать байты произвольного объекта в памяти как целочисленный тип? Вообще, какое решение будет правильным? Как эта проблема решена в std::unordered_map или QMap?


Ответ

Классы наподобие unordered_set вычисляют хеш не сами, а используют std::hash (а также дают возможность пользователю указать свою реализацию хеширования, если он недоволен стандартной, или если её не существует).
std::hash, в свою очередь, тоже не пользуется никакой особой магией, а просто имеет шаблонные специализации для примитивных типов, строк и указателей (обычных и «умных»).
Мне кажется, вам стоит не изобретать велосипед, а воспользоваться той же идеей. А ещё проще, просто используйте std::hash. Поверьте, в написании контейнера есть много сложностей помимо этой.

Таким образом, просто используйте
size_t hash_value = std::hash()(t);

Как прикрепить ViewModel к UserControl?

Как прикрепить ViewModel к UserControl? В случае с window всегда делал так:
new MainWindow() { DataContext = new MainVm() };
Если делать так для UserControl то компилятор ругается. Как нужно действовать в данной ситуации?
P.S. Для общей картины обьясню к какому эффекту я стремлюсь: есть главное окно, и в зависимости от нажатий пользователся должны отображатся разные, никак не связанные между собой данные. Поэтому для каждых из этих данных я хочу создать отдельные UserControl и Vm, и по надобности просто подменять один UserControl на другой. Если у меня неправильный подход, поправьте меня.


Ответ

Контрол не должен устанавливать себе сам DataContext. DataContext должен устанавливать родительский элемент. Делайте как-то так:

То есть: нужные VM для частей, которые представляются в виде контролов, должны быть в MainVM как свойства. (Таким образом, кстати, все VM смогут общаться через центральную VM.)
Надеюсь, вы поняли идею.

Кстати, и главное окно тоже не должно создавать себе VM. Обычно делается так:


public partial class App : Application { MainVM mainVM = new MainVM();
protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); new MainWindow() { DataContext = mainVM }.Show(); } }

Ввод данных в С. Не определяется GetString() из cs50

Почему у меня не определяется string s = GetString();?
hell.c
#include #include
int main(void) { printf("State our name: "); string s = GetString(); printf("hello, %s
", s); }
cc hell.c -o hell
/tmp/ccHZXs2m.o: In function `main' hell.c:(.text+0x16): undefined reference to `GetString' collect2: error: ld returned 1 exit status make: *** [hell] Error 1


Ответ

Почему бы тебе не воспользоваться методом scanf() для чтения с консоли?
int main(void) { string name; printf("Введите ваше имя"); scanf("%s", name); printf("Привет, %s
!", name); return 0; }

Как правильно работать с экземпляром класса на двух страницах? C#/UWP

Есть две страницы, на первой я создаю экземпляр класса, в который я добавляю данные. Перехожу на вторую страницу и они отображаются. Но когда я заново захожу на первую страницу, и создаю новые данные, они перезаписывают уже имеющиеся, а не добавляются. Я так понимаю, должен быть один экземпляр класса, в который я каждый раз буду добавлять данные, но как это реализовать?


Ответ

Я нашел решение, воспользовавшись передачей объекта класса как параметра во время перехода на другую страницу.
Frame.Navigate(typeof(Page), DS);
Где DS это то, что мы хотим передать, а Page та страница на которую переходим.

Библиотеки для графиков

Есть ли какие-нибудь библиотеки для работы с графиками на Android?


Ответ

Open source библиотека Graph View. Сайт | GitHub MPAndroidChart - open source, поддерживаем множество видов графиков. GitHub Androidplot - open source, также поддерживает множество видов графиков. Сайт | GitHub | Bitbucket HelloCharts. GitHub Платная библиотека Chart. Сайт Платная библиотека aiCharts. Сайт

Проблема при установке Oracle JDK на Debian

Возникла ошибка при установке Oracle JDK на Debian 8 Jessie
rostislav@Rostislav-PC:~/Загрузки$ sudo dpkg -i jdk1.8.0-91_1.8.091-1_amd64.deb Выбор ранее не выбранного пакета jdk1.8.0-91. (Чтение базы данных … на данный момент установлено 119167 файлов и каталогов.) Подготовка к распаковке jdk1.8.0-91_1.8.091-1_amd64.deb … Распаковывается jdk1.8.0-91 (1.8.091-1) … Настраивается пакет jdk1.8.0-91 (1.8.091-1) … Unpacking JAR files... tools.jar... plugin.jar... javaws.jar... deploy.jar... rt.jar... jsse.jar... charsets.jar... localedata.jar... jfxrt.jar... /var/lib/dpkg/info/jdk1.8.0-91.postinst: line 641: /usr/sbin/alternatives: Нет такого файла или каталога /var/lib/dpkg/info/jdk1.8.0-91.postinst: line 653: /usr/sbin/alternatives: Нет такого файла или каталога dpkg: ошибка при обработке пакета jdk1.8.0-91 (--install): подпроцесс установлен сценарий post-installation возвратил код ошибки 127 При обработке следующих пакетов произошли ошибки: jdk1.8.0-91
Процесс установки был таким (инструкцию нашел тут):
Скачал официальную версию JDK с сайта Oracle. Установил alien из официального репозитория. Перегнал .rpm в .deb командой sudo alien --scripts jdk-8u91-linux-x64.rpm Установил .deb пакет командой sudo dpkg -i jdk1.8.0-91_1.8.091-1_amd64.deb, во время чего и возникла ошибка
Из-за чего произошла ошибка и как ее исправить?

UPD_0 (kvm): При попытке удалить JDK:
rostislav@Rostislav-PC:~$ dpkg --remove --force-remove-reinstreq jdk1.8.0-91 dpkg: ошибка: запрошенная операция требует привилегий суперпользователя rostislav@Rostislav-PC:~$ sudo dpkg --remove --force-remove-reinstreq jdk1.8.0-91 (Чтение базы данных … на данный момент установлено 116630 файлов и каталогов.) Удаляется jdk1.8.0-91 (1.8.091-1) … /var/lib/dpkg/info/jdk1.8.0-91.postrm: line 586: /usr/sbin/alternatives: Нет такого файла или каталога /var/lib/dpkg/info/jdk1.8.0-91.postrm: line 598: /usr/sbin/alternatives: Нет такого файла или каталога dpkg: ошибка при обработке пакета jdk1.8.0-91 (--remove): подпроцесс установлен сценарий post-removal возвратил код ошибки 127 При обработке следующих пакетов произошли ошибки: jdk1.8.0-91 rostislav@Rostislav-PC:~$ sudo dpkg --purge --force-remove-reinstreq jdk1.8.0-91(Чтение базы данных … на данный момент установлено 116630 файлов и каталогов.) Удаляется jdk1.8.0-91 (1.8.091-1) … /var/lib/dpkg/info/jdk1.8.0-91.postrm: line 586: /usr/sbin/alternatives: Нет такого файла или каталога /var/lib/dpkg/info/jdk1.8.0-91.postrm: line 598: /usr/sbin/alternatives: Нет такого файла или каталога dpkg: ошибка при обработке пакета jdk1.8.0-91 (--purge): подпроцесс установлен сценарий post-removal возвратил код ошибки 127 При обработке следующих пакетов произошли ошибки: jdk1.8.0-91


Ответ

Установить JDK из rpm это целое приключение, лучше воспользоваться java-package
Убедитесь, что подключены contrib архивы в /etc/apt/sources.list
deb jessie main contrib non-free
Установите java-package: apt install java-package Скачайте JDK с сайта Oracle, но не rpm, а tar.gz. Запустите создание deb-пакета JDK:
fakeroot make-jpkg jdk-8u91-linux-x64.tar.gz
Возможно, появятся ошибки о неудовлетворенных зависимостях, установите пакеты, о которых говорится в ошибках, затем заново запустите создание пакета. В моем случае было:
sudo apt install libgl1-mesa-glx libxslt1.1 libxtst6 libxxf86vm1
Удалите старый некорректно установленный пакет JDK. Установите созданный пакет
sudo dpkg -i oracle-java8-jdk_8u91_amd64.deb


UPD1. Если снести кривой пакет JDK через apt remove jdk1.8.0-91 не удается, удаляем его принудительно:
sudo dpkg --remove --force-remove-reinstreq jdk1.8.0-91 sudo dpkg --purge --force-remove-reinstreq jdk1.8.0-91

UPD2. Создайте симлинк
sudo ln -s /usr/sbin/update-alternatives /usr/sbin/alternatives
и еще раз попробуйте снести. Потом удалите симлинк.

Универсальный класс с параметром в виде универсального класса

Возможно ли, и если да, то как, создать универсальный (generic) класс, параметром для которого выступает другой универсальный класс?
Псевдо-код поясняющий идею:
class Gen where T : class { } // тут всё ОК class MoreGen where G : Gen { } // здесь непонятно как сделать
Хочется ограничить параметры для MoreGen только классами Gen, чтобы была возможность использовать следующий код:
new MoreGen>(); // Должно быть OK new MoreGen(); // Нужна ошибка компиляции new MoreGen>(); // Нужна ошибка компиляции


Ответ

На основании упомянутого в комментариях ответа на английском SO, решение "в лоб" не является возможным. Для достижения желаемого эффекта приходится добавлять интерфейс:
interface IGen {} class Gen : IGen where T : class { } class MoreGen where G : IGen { }
public class Test { public static void Main() { new MoreGen>(); // OK new MoreGen>(); // OK // new MoreGen(); // no implicit reference conversion from `string' to `IGen' // new MoreGen>(); // The type `int' must be a reference type } }
Результат выполнения кода

Регулярное выражение лишние символы

Есть задача, написать регулярное выражение на пропуск 2х слов, к примеру имя и фамилия, на любом языке (англ, немецкий...).
Вот как я подумал
var str = "Имя фамилия текст текст"; str.match(/^[^!@#]+ [^!@#]+$/i);
И вот результат
["Имя фамилия текст текст"]
Почему , регулярное выражение прошло валидацию? МОжет я не правильно проверяю, я не пойму...
По идее, регулярка должна найти совпадение
начало_строки[любой_символ_кроме!@#]минимум1раз пробел [любой_символ_кроме!@#]конец_строки
Но, в примере после 2ого слова есть еще пробелы, символы, и их тоже пропускает
Мне нужно проверить на любые символы кроме тех 3х знаков
Вот тестер https://regex101.com/r/kJ5vZ2/4


Ответ

Вы сами отвечаете на свой вопрос. Регулярное выражение [^!@#]+ включает в себя любые символы кроме !, @ и # в том числе включает и пробел! А это значит, что вся строка Имя фамилия текст текст подходит под первое [^!@#]+. Добавьте в список исключаемых слов пробел
Пример:
var str = "Имя фамилия текст текст"; str.match(/^[^!@# ]+ [^!@# ]+$/i);
https://regex101.com/r/kJ5vZ2/5

Почему индекс в методе pop находится вне границы?

import random WORDS = ["Svitanok", "hogog", "gfgfgfg", "sdasd", "adam"] newwords = [] length = len(WORDS) newpos = "" while WORDS: newpos = random.randint(0, length-1) newwords.append(WORDS.pop(newpos)) WORDS.remove(WORDS[newpos]) print(newwords)
В общем, писал алгоритм для вывода списка WORDS в случайном порядке. И наткнулся на ошибку "pop index out of range". Не могу понять, почему метод выходит за границы? P.S. Про shuffle я знаю, просто хочу написать код таким способом.


Ответ

remove не нужно вызывать, pop уже удаляет элемент из списка. Кроме этого, значение length нужно обновлять на каждой итерации, тк список WORDS изменяет свой размер.

PostgreSQL: максимальное и текущее количество соединений

Как можно узнать максимальное и текущее количество установленных соединений на сервере PostgreSQL?


Ответ

За максимальное количество соединений отвечает параметр max_connections, получить который можно при помощи запроса
SHOW max_connections;
Количество подключенных к серверу соединений можно получить, выполнив запрос
SELECT COUNT(*) FROM pg_stat_activity;

Запись радиоэфира с пропуском тишины в Linux

Доброго времени суток. Имеется трансивер, подключённый к линейному входу ПК под управлением убунты. Задача - вести запись вызывной частоты. Подскажите, какой программой можно захватывать линейный вход с пропуском тишины так, чтобы записи сохранялись в разные файлы с названием равным времени, в которое была сделана запись. Ещё лучше, если есть возможность писать всё в один файл, если тишина длилась, например, не более минуты. (Чтобы в один файл попадал, например, общий вызов и все отклики на него. А как только тишина длится более минуты - то следующая запись пойдёт в новый файл.)


Ответ

есть программа streamripper
которой я записывал потоковое радио. Может писать в один файл. Может не записывать тишину.

Как получить данные из onResponse? Retrofit.

Не могу получить данные из onResponse.
public void loadData() { Retrofit retrofit = new Retrofit.Builder() .baseUrl(myurl) .addConverterFactory(GsonConverterFactory.create()) .build(); RESTPK service = retrofit.create(RESTPK.class); Call call = service.loadJsonStr(); call.enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { pathPoster = response.body().getPath().get(0).get1(); //переменая которую мне нужно вытащить System.out.println(pathPoster); } @Override public void onFailure(Call call, Throwable t) { } }); }
Если в onResponse вывести на экран переменную pathPoster, то она показывает правильный результат, но если ее вывести на экран после вызова loadData(), то в ней уже ничего нет и приложение вылетает с ошибкой. Получить данные получил, но пользоваться ими не получается.
loadData(); System.out.println(pathPoster);
ошибка:
FATAL EXCEPTION: mainjava.lang.RuntimeException: Unable to start activity ComponentInfo{com.awesomedevelop.recyclerview/com.awesomedevelop.recyclerview.MainActivity}: java.lang.NullPointerException


Ответ

Потому что у тебя асинхронный запрос. onResponse вызывается после загрузки информации, а System.out.println(pathPoster) вызывается до загрузки, судя по твоему коду. То есть, когда информация еще не успела загрузиться из сети. А падает потому что строка в которую ты не записал еще данные по-умолчанию null.
Либо делай синхронный запрос, либо все действия после загрузки выполняй в onResponse.
Если переделаешь на синхронный запрос, учти, что синхронные запросы в сеть, нельзя делать в Ui потоке приложения.
http://square.github.io/retrofit/2.x/retrofit/

Валидное расположение блоков

Подскажите как грамотно расположить блоки как на данном рисунке(блок 3 немного заезжает на блок 1,), что б они сохранили при этом адаптивность свою(при изменении ширины экрана не проваливались ни куда). Можно и на бутстрапе, просто интересен грамотный подход, да бы минимизировать использование лишних тегов и стилей.Заранее спасибо


Ответ

css - calc()
browser support calc
.block-1 { height: 200px; background: #ccc; } .block-2, .block-3 { height: 100px; background: #ddd; } .block-3 { height: 100px; background: #999; margin-left: -50px; width: calc(100% + 50px)!important; } @media screen and (max-width: 767px) { .block-3 { margin-left: 0; width: 100%!important; } }

1
2
3

Правильная замена классов в галерее

Есть слайдер с js-анимацией. Анимирование происходит путем подмены класса, их координаты заданы в css и в js - circleCoords.
Код выкладываю на plunker, т.к. его много и чтоб понять проблему нужно увидеть событие глазами: https://plnkr.co/edit/qHn1HytgxucUwl0tkBTe?p=preview
Перед тем как мы еще не кликали на элемент карусели, функция animate каждый раз принимает массив с именами классов, на каждой итерации последний в списке элемент массива ставится на перед (происходит циклический сдвиг). При клике на элемент, мы меняем очередность элементов в массиве, и подаем его в функцию animate в соответствующем порядке после изменений классов в html-дереве.
Но почему-то, после клика, элементы начинают сдвигаться беспорядочно, а не как следует - друг за другом в новой построенной очереди. Я уверен что где-то пропустил какую-то мелочь, нужен свежий взгляд профи) Благодарен за внимание!


Ответ

немного упростил код, смотреть результат лучше на всю страницу.
var dd = $("[data-id]"), elems = $.makeArray(dd), circleCoords = [{ top: 0, left: 229 }, { top: 100, left: 677 }, { top: 265, left: 603 }, { top: 265, left: 307 }, { top: 265, left: 14 }, { top: 100, left: -58 }]; dd.on("click", function() { var i = $.inArray(this, elems); elems[i] = elems[0]; elems[0] = this; $(elems[i]).removeClass("active"); move() }); function move() { var deferreds = []; $(elems[0]).addClass("active"); $.each(elems, function(indx, el) { deferreds.push($(el).animate(circleCoords[indx],2000)) }); $.when.apply(null, deferreds).done(function() { if (!busy) timer = window.setTimeout(function() { var el = elems.pop(); $(elems[0]).removeClass("active"); elems.unshift(el); move() }, 2000) }) } var busy, timer; $(".container").mouseleave(function() { busy = false; !dd.queue("fx").length && move() }).mouseenter(function() { window.clearTimeout(timer); busy = true }); move() .container { padding-top: 30px; } .animation-wrap { position: relative; width: 1170px; height: 565px; margin: auto; overflow: hidden; } .animation-wrap a { display: none; position: absolute; width: 119px; height: 30px; z-index: 72; top: 279px; left: 196px; } .animation-wrap .small { position: absolute; width: 222px; height: 131px; left: 50%; top: 50%; margin-left: -138px; margin-top: -81px; cursor: pointer; z-index: 2; opacity: 1; -webkit-transition: all 0.7s ease; -moz-transition: all 0.7s ease; -ms-transition: all 0.7s ease; -o-transition: all 0.7s ease; transition: all 0.7s ease; } .animation-wrap .small:hover { -webkit-filter: brightness(130%); filter: brightness(130%); } .animation-wrap .big { position: absolute; opacity: 0; margin: 0 auto; -webkit-transition: all 0.7s ease; -moz-transition: all 0.7s ease; -ms-transition: all 0.7s ease; -o-transition: all 0.7s ease; transition: all 0.7s ease; } .active .small { opacity: 0; cursor: default; } .active .big { opacity: 1; z-index: 3; width: 507px; height: 360px; } [data-id] { position: absolute; width: 400px; height: 380px; } [data-id=obj1] { top: 70px; left: -165px; } [data-id=obj2] { top: 0; left: 285px; } [data-id=obj3] { top: 70px; left: 730px; } [data-id=obj4] { top: 285px; left: 610px; } [data-id=obj5] { top: 285px; left: 285px; } [data-id=obj6] { top: 285px; left: -40px; }


Фиксированное значение столбца (= null) в зависимости от значения другого столбца

В таблице tablename есть столбцы type и arg. Нужно ввести ограничение, по которому при type = 1, всегда arg = null
Каким образом это можно организовать в PostgreSQL? Версия 9.5.2.
Можно реализовать это на уровне приложения, но требуют, именно, на уровне СУБД. Чтобы она не дала нарушить это правило.


Ответ

ALTER TABLE test ADD CONSTRAINT null_arg CHECK ((type = 1 AND arg IS NULL) OR type <> 1)

Как восстановить базу данных из *.MYD *MYI *FRM?

У нас упал сайт и хостер предоставил данные файлы для восстановления.
Какие данные, кроме упомянутых файлов, потребуются для восстановления?


Ответ

Какие данные, кроме упомянутых файлов, потребуются для восстановления?
если все таблицы хранились в вашей базе данных только с использованием движка myisam, то перечисленных файлов, по идее, должно быть достаточно
Each MyISAM table is stored on disk in three files. The files have names that begin with the table name and have an extension to indicate the file type. An .frm file stores the table format. The data file has an .MYD (MYData) extension. The index file has an .MYI (MYIndex) extension.
разве что ещё файл db.opt потребуется с глобальными для базы данных настройками (типа набора символов по умолчанию и т.п.).

все эти файлы хранятся в каталоге, носящем имя базы данных (он расположен обычно в каталоге с данными mysqld: часто это /var/lib/mysql). вот полное содержимое этого каталога (носящего имя вашей базы данных) вам и потребуется.
скопируйте этот каталог внуть каталога с данными mysqld (выставив каталогу и файлам права и принадлежность как у «соседних» баз данных) и перезапустите mysqld — сервер после этого должен «подхватить» новую базу данных (она должна быть видна в списке, выдаваемом командой show databases).

если же хотя бы одна таблица использовала довольно популярный ныне движок innodb, то ситуация несколько сложнее. описание таблицы, понятно, хранилось в каталоге базы данных в файле имя-таблицы.frm. а вот сами данные таблицы могли храниться в существенно разных местах:
если глобальная конфигурационная переменная на старом сервере innodb_file_per_table имела значение off, то данные всех таблиц из всех баз данных хранились в одном файле, и хостер вряд ли его вам предоставит. если же эта глобальная переменная была установлена в on, то данные для каждой innodb-таблицы хранились в файлах имя-таблицы.ibd внутри каталога с вашей базой данных.

Генерация всех подмножеств множества мощности n,которые не содержат соседних элементов

Предположим у меня есть множество A={1,2,...,n}.(длинна n известна)
Как мне сгенерировать все подмножества,которые не содержат соседних елементов?" (к примеру,если я беру элемент 2 из A, то то элементы 1 и 3 я взять уже не могу)
P.S:Сначала думал просто сгенрировать все подмножества, а потом выбрать те,которые не содержат соседних элементов.Но такой подход очень не эффективен.
P.P.S.:рекурсией пользоваться нельзя


Ответ

Стоит начать с того, что максимальная мощность такого подмножества будет ceil(n/2). Минимальная - единица. Соответсвенно, нужно сгенерировать все подмножества длиной 1, затем длиной 2, затем ..., и так далее до ceil(n / 2). Суть данного решения в том, что есть зафиксированные элементы и итератор, который добирает из множества нужное количество элементов. Например для подмножеств мощностью 2: есть подмножества {1,3}, {1,4}, {1,5}, {1,6}. Фиксированный элемент здесь - 1, и итератор собирает все элементы последовательно, начиная с 3. Когда итератор дойдет до конца - фиксированный элемент меняется. Так как подмножества могут быть длиннее, чем 2, то фиксированный элемент - это тоже множество - переменная subset_base. Для каждого нового "уровня" (для подмножества с мощностью + 1) - фиксированные элементы не генерируются заново, а берутся прямиком с предыдущего уровня и затем дополняются. Ключевая строка, пожалуй - это subset_first = tpl[1] + 2 - именно здесь определяется, что сосед не попадет в подмножество. Можно изменять слагаемое 2, определяя критерий "соседства".
Необходимо n / 2 раз пройти по всему множеству. Таким образом сложность O(n^2).
import math
A = {1, 2, 3, 4, 5, 6, 7, 8}
subsets = [{elem} for elem in A] A = sorted(list(A)) # Для удобства seeker_position = 0 subset_first = 0
subset_length = 2
base_subsets_for_next_level = [({elem}, index) for index, elem in enumerate(A)]
while subset_length <= math.ceil(len(A) / 2): helper = [] for tpl in base_subsets_for_next_level: subset_base = tpl[0] subset_first = tpl[1] + 2 while subset_first < len(A): subset = subset_base | {A[subset_first]} subsets.append(subset ) helper.append((subset, subset_first)) subset_first += 1 base_subsets_for_next_level = helper seeker_position += 1 if seeker_position + 2 * (subset_length - 1) >= len(A): subset_length += 1 seeker_position = 0
subsets.append({}) # Пустое множество print(subsets)
Результат: [set([1]), set([2]), set([3]), set([4]), set([5]), set([6]), set([7]), set([8]), set([1, 3]), set([1, 4]), set([1, 5]), set([1, 6]), set([1, 7]), set([8, 1]), set([2, 4]), set([2, 5]), set([2, 6]), set([2, 7]), set([8, 2]), set([3, 5]), set([3, 6]), set([3, 7]), set([8, 3]), set([4, 6]), set([4, 7]), set([8, 4]), set([5, 7]), set([8, 5]), set([8, 6]), set([1, 3, 5]), set([1, 3, 6]), set([1, 3, 7]), set([8, 1, 3]), set([1, 4, 6]), set([1, 4, 7]), set([8, 1, 4]), set([1, 5, 7]), set([8, 1, 5]), set([8, 1, 6]), set([2, 4, 6]), set([2, 4, 7]), set([8, 2, 4]), set([2, 5, 7]), set([8, 2, 5]), set([8, 2, 6]), set([3, 5, 7]), set([8, 3, 5]), set([8, 3, 6]), set([8, 4, 6]), set([1, 3, 5, 7]), set([8, 1, 3, 5]), set([8, 1, 3, 6]), set([8, 1, 4, 6]), set([8, 2, 4, 6])]
`

Повторение результата при возведении в степень

Как мне вычислить все возведения в степень с x_min ^ y_min по x_max ^ y_max без повторов результатов. Например:
x2 ^ x8 = z ... x85 ^ y23 = p ... но x85 ^ y28 = z !
Как видно, результат z повторяется у разных вычислений, каким образом можно пропускать все следующие вычисления при условии, что сравнивать с ранее вычисленными результатами не допустимо?
# code python 3 min_x, max_x = 5, 127 min_y, max_y = 2, 250 result = '' for x in range(min_x, max_x): for y in range(min_y, max_y): result += str(x ** y)


Ответ

UPDATE: - только что проверил с вашими числами - Python "занимал" около 1GB памяти, timing я обновил для ваших чисел
In [105]: x = np.arange(5, 8800, dtype=np.uint64)
In [106]: y = np.arange(2, 8250, dtype=np.uint64)
In [107]: r = np.unique(np.array([np.power(x, np.repeat([pw], len(x))) for pw in np.nditer(y)]))
In [108]: len(''.join(r.astype(str))) Out[108]: 457656
In [109]: %timeit np.unique(np.array([np.power(x, np.repeat([pw], len(x))) for pw in np.nditer(y)])) 1 loop, best of 3: 11.3 s per loop
In [115]: np.version.version Out[115]: '1.10.4'
numpy solution:
x = np.arange(5, 127, dtype=np.uint64) y = np.arange(2, 250, dtype=np.uint64)
r = np.unique(np.array([np.power(x, np.repeat([pw], len(x))) for pw in np.nditer(y)]))
# чтобы сэкономить память записываем строку в `r` r = ''.join(r.astype(str)) print(r)
Timing для 5000 x 5000 массива:
In [102]: %timeit np.unique(np.array([np.power(x, np.repeat([pw], len(x))) for pw in np.nditer(y)])) 1 loop, best of 3: 3.89 s per loop
In [103]: x.shape Out[103]: (4995,)
In [104]: y.shape Out[104]: (4998,)

MediaPlayer воспроизведение

На сайте нашёл код:
public void onClick (View v){ index = 0; mp = MediaPlayer.create(getApplicationContext(), sounds[index] ); mp.setLooping(false); mp.start(); mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){ public void onCompletion(MediaPlayer mp){ if(index < sounds.length-1){ index++; mp = MediaPlayer.create(getApplicationContext(), sounds[index]); mp.start(); mp.setOnCompletionListener(this); } else mp.release(); } }); }
Но он воспроизводит все треки друг за другом. Может кто-нибудь подскажет: как сделать при нажатии на кнопку воспроизведение одного трека? И пока трек воспроизводится, кнопка должна быть неактивна, а следующее нажатие воспроизводит второй трек. И ещё как сделать управление с кнопки громкости+ ?


Ответ

Так пропишите такое поведение. При нажатии делаете кнопку неактивной, а по окончании возвращаете:
int index = 0; //дабы не сбрасывалось по нажатию на кнопку выносим public void onClick (View v){ yourButton.setEnabled(false); //кнопка неактивна mp = MediaPlayer.create(getApplicationContext(), sounds[index]); mp.setLooping(false); mp.start(); mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){ public void onCompletion(MediaPlayer mp){ yourButton.setEnabled(true); //после окончания воспроизведения делаем кнопку активной mp.release(); if(index < sounds.length-1){ index++; //увеличиваем счетчик для воспроизведения следующего трека } else { index = 0; //сбрасываем в 0 } } }); }

Как высчитать скидку?

Всем привет. Есть 3 таблицы - Скидки(Discount), Клиенты(Clients) и Заказы(Orders)
Discount
id_discount count_orders percent_discount 1 5 1,5 2 10 2,5
Clients
id_client Name Surname 1 Ivan Petrov 2 Vasya Vasev
Orders
id order_sum id_client
Вопрос, как посчитать общую сумму, учитывая количество заказов, который сделал клиент? Если общее кол-во заказов 5 и выше, то идет скидка в 1.5%, если 10 и выше, то 2.5%. В противном случае скидки нет. Заранее спасибо


Ответ

Firebird нет под руками, так что пишу максимально приближенный к стандартам запрос, сработает с высокой вероятностью. Вы не указали к какой конкретно сумме вы хотите применить скидку, поэтому посчитал, что следует выдать все заказы, вычислив для каждого из них сумму со скидкой, с предположением что в данный момент в заказах сумма без скидки.
select O.id,O.id_client, O.order_sum-(O.order_sum/100*coalesce(D.percent_discount,0)) from Orders O left join (select id_client,max(D.count_orders) as d_cnt from (select id_client,count(1) as cnt from Orders group by id_client) as C, Discount as D where D.count_orders<=cnt group by id_client) as S on S.id_client=O.id_client left join Discount as D on D.count_orders=S.d_cnt
Подзапрос C выбирает текущие количества заказов по клиентам К ним клеются все скидки с меньшим или равным количеством Подзапрос S. Берется количество для скидки для максимально подошедшего кол-ва заказов По left (т.к. скидки может и не быть) доклеиваются скидки с учетом нужного количества
Таблицу clients приклеить по желанию.

Python. Как работает генератор списка с lambda

Написал вот такую строчку:
a = [lambda x : x^n for n in range(10)]
При этом на каждой итерации
for i in range(10): print(a[i](2))
выдает 11, a
for i in range(10): print(a[2](i))
выдет: 9 8 11 10 13 12 15 14 1 0
Почему?


Ответ

Если я правильно понял, то происходит следующее:
a = [lambda x : x^n for n in range(10)] - тут создается список функций. Это то же самое, что и:
def xoring(x): for n in range(10): pass return x^n
a = [] for i in range(10): a.append(xoring)
Можно даже посмотреть что внутри списка и увидеть набор функций:
>>> a [. at 0x029E1468>, . at 0x02B7C300>, . at 0x02B7C348>, . at 0x02B7C390>, . at 0x02B7C3D8>, . at 0x02B7C420>, . at 0x02B7C468>, . at 0x02B7C4B0>, . at 0x02B7C4F8>, . at 0x02B7C540>]
Далее, for i in range(10): print(a[i](2)), 10 раз вызывается i-я функция из списка a и ей передается аргумент 2. Так как функции одинаковые, то и результаты одинаковые. Т.е. внутри происходит следующее:
lambda x : x^n for n in range(10) - здесь i изменяется от 0 до 9 и ксорится с x. Т.к. x = 2, то x^i даст такие результаты:
2^ 0 = 2 2^ 1 = 3 2^ 2 = 0 2^ 3 = 1 2^ 4 = 6 2^ 5 = 7 2^ 6 = 4 2^ 7 = 5 2^ 8 = 10 2^ 9 = 11
Последнее значения и возвращает функция.
Здесь for i in range(10): print(a[2](i)) 10 раз вызывается функция с индексом 2 в списке a и ей передается значение i, которое меняется от 0 до 9. То же самое, что и
for i in range(10): print(xoring(i))
Что в результате и дает
0 ^ 9 = 9 1 ^ 9 = 8 2 ^ 9 = 11 3 ^ 9 = 10 4 ^ 9 = 13 5 ^ 9 = 12 6 ^ 9 = 15 7 ^ 9 = 14 8 ^ 9 = 1 9 ^ 9 = 0

WebStorm Git (git repository cannot be cloned to an existing directory)

В чем проблема?
12:53:22 Created Git repository in /Applications/MAMP/htdocs/workout_test 12:59:47 Update canceled 12:59:47 Can't update: no tracked branch No tracked branch configured for branch master. To make your branch track a remote branch call, for example, git branch --set-upstream master origin/master*


Ответ

Думаю вот это должен сработать:
git init git remote add origin PATH/TO/REPO git fetch git checkout -t origin/master
Информация взята отсюда

Что обозначают атрибуты name и content у метки meta?

Что обозначают данные атрибуты у метки meta?


Ответ

это мета тег для определения устройства с которого зашли на сайт, initial-scale - это маштаб страницы изначально, а width=device-width oпределяет ширину viewporta, подробнее почитайте вот тут http://frontender.com.ua/mobile-web/wtf-viewport/

Как занести данные из HTML-формы в MySQL при помощи JDBC?

Имеются 2 HTML-формы

и

База данных на MySQL Server, где присутствуют аналогичные поля login varchar (45) NOT NULL и password varchar (45) NOT NULL.
Подскажите, как при помощи JDBC записать данные HTML-формы в БД MySQL. PHP не предлагать, можно другие Java-технологии.


Ответ

Быстрая реализация с использование сервлета:
html


TheFirstServlet
public class FirstServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); }
@Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); request.setCharacterEncoding("UTF-8"); String login = request.getParameter("login"); String password = request.getParameter("password"); insert(login, password); PrintWriter printWriter; try { printWriter = response.getWriter(); printWriter.println("Ну, попытались"); } catch(IOException exc) {} }
public void insert(String login, String password) { Connection conn = null; Statement stmt = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc.url", "jdbc.login", "jdbc.password"); stmt = conn.createStatement(); String sql = "INSERT INTO NAME_TABLE (`login`,`password`)" + "VALUES ('" + login + "','" + password + "')"; stmt.executeUpdate(sql); } catch (SQLException | ClassNotFoundException exc) { exc.printStackTrace(); System.out.println("Не записал"); } finally { try { if(conn!=null) conn.close(); if(stmt!=null) stmt.close(); } catch (SQLException exc) {} } }
Ну, как-то так по-простому.

Проблемы с чтением файла через javascript

Есть функция, где я пытаюсь записать в переменную данные текстового файла с сервера
function loadModel(){ var cookiePath = readCookie('modelID'); var modelPath = "../modelbase/php_base/models/"+cookiePath+".zedit"; var rawFile = new XMLHttpRequest(); rawFile.open("GET", modelPath, false); rawFile.onreadystatechange = function () { if(rawFile.readyState === 4) { if(rawFile.status === 200 || rawFile.status == 0) { var modelText = rawFile.responseText; alert(modelText); } } } rawFile.send(null); }
Но при попытке считывания в консоль получаю предупреждение (на строке rawFile.open...):
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/
Есть ли какой-то способ получить данные из нужного файла?


Ответ

Предупреждение говорит вам:
"Вы пытаетесь отправить синхронный xhr запрос. Отправлять синхронные запросы больше не модно, потому что юзерам не нравится ждать."
За синхронность/асинхронность xhr отвечает третий параметр функции xhr.open Можно поставить его в true или вообще убрать (он true по умолчанию).

Как запретить анимацию togglebutton?

Знатоки, подскажите пожалуйста, каким образом я могу запретить анимацию нажатия ToggleButton ? Если кнопка нажата, то другая автоматически меняет стиль на не нажатую, но если я нажму на кнопку, которая нажата - она отжимается - как запретить этот "отжим" ?


Ответ

Можно просто обработать событие Click для каждого ToogleButton

Обработчики :
private void Toogle1_OnClick(object sender, RoutedEventArgs e) { var button = (ToggleButton)e.OriginalSource; if ((bool)button.IsChecked) { button.IsEnabled = false; toogle2.IsChecked = false; toogle2.IsEnabled = true; } }
private void Toogle2_OnClick(object sender, RoutedEventArgs e) { var button = (ToggleButton)e.OriginalSource; if ((bool)button.IsChecked) { button.IsEnabled = false; toogle1.IsChecked = false; toogle1.IsEnabled = true; } }

Переименование окон и вкладок эмулятора терминала

В Debian 8 (Jessie) возможно ли изменять названия окон (вкладок) на произвольные значения? Интересует прежде всего Terminal и его вкладки.
На данный момент контекстные меню для вкладок и для окон (Alt+Space) не содержат подобных действий, хотя в Ubuntu же, например, возможность переименования вкладок терминала имелась.


Ответ

многие реализации эмуляторов терминала для x-window system перехватывают escape-последовательность такого вида
\x1b]0;заголовок для окна и иконки\x07 \x1b]1;заголовок только для иконки\x07 \x1b]2;заголовок только для окна\x07
и устанавливают заголовок окна и/или иконки в панели задач.
отправить последовательность можно, например, программой echo
$ echo -e '\x1b]0;заголовок для окна и иконки\x07'

значения символов "escape" (шестнадцатиричное 1b) и "bell" (7) можно задать и в восьмиричной форме: \033 и \007

Не работает text-overflow

Не работает text-overflow. Каким образом решается данная проблема?
.item { padding: 10px 10px; border-top: 1px solid #DCDCDC; border-bottom: 1px solid #DCDCDC; background: #F7F7F7; margin-bottom: 5px; position: relative; } #description { color: black; text-overflow: ellipsis; }

Заголовок
Задает все свойства фона элемента страницы в один прием. Заменяет собой атрибуты background-attachment, background-color, background-image, background-position и background-repeat.


Ответ

С помощью двух данных свойств можно "починить" text-overflow.
white-space: nowrap - запрещаем делать перенос на другую строку. overflow: hidden - непосредственно скрываем текст, выходящий за рамки контейнера, для того чтобы в силу вступило свойство text-overflow.
.search_page_item { padding: 10px 10px; border-top: 1px solid #DCDCDC; border-bottom: 1px solid #DCDCDC; background: #F7F7F7; margin-bottom: 5px; position: relative; } #description { color: black; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; }

Заголовок
Задает все свойства фона элемента страницы в один прием. Заменяет собой атрибуты background-attachment, background-color, background-image, background-position и background-repeat.

маркеры из локальной базы данных

Как правильно сделать запрос для вывода маркеров на андроид устройстве (на google maps). Я подключаюсь к json, но ничего не происходит. Подскажите, как это делается.
Обновление
Вот ссылка на json, мне нужно вывести маркеры в приложении.


Ответ

Добавить маркер можно так:
map.addMarker(new MarkerOptions() .position(new LatLng(10, 10)) .title("Hello world"));
Вам необходимо из ответа с сервера вытянуть координаты и добавить на карту:
private void fun(GoogleMap map, String response) throws JSONException { JSONObject object = new JSONObject(response); JSONArray arr = object.getJSONArray("markers"); for (int i=0; i

Как вывести файл Xml деревом в консоль с рекурсией. Вроде все читается, но вот как вывести именно деревом, как и сам файл Xml никак не соображу

вот код
using System.Text; using System.Xml; using System.Xml.Linq; using System.IO;
namespace TestApp_Dipl { class Program { static int iter; static void Main(string[] args) { Program ThisClass = new Program(); Console.WriteLine("Main"); XmlDocument XmlDoc = new XmlDocument(); XmlDoc.Load("File.xml"); XmlNodeList _fnames = XmlDoc.GetElementsByTagName("CD"); Console.WriteLine(_fnames.Count.ToString()); ThisClass.GetNodes(_fnames);

Console.ReadKey(); }
void GetNodes(XmlNodeList NodeListVar) { int i = 1; foreach (XmlNode el in NodeListVar) { if (el.HasChildNodes) { Console.WriteLine(i++ + ". " + el.Name); GetNodes(el.ChildNodes); } else { Console.WriteLine("-> " + el.InnerText); } } }
} }
Xml file.xml
Empire Burlesque Bob Dylan USA Columbia 10.90 1985 Hide your heart Bonnie Tyler UK CBS Records 9.90 1988
Хотелось бы в консоли получить так:
CATALOG 1.CD TITLE Empire Burlesque ARTIST Bob Dylan COUNTRY USA COMPANY Columbia PRICE 10.90 YEAR 1985 2.CD TITLE Hide your heart ARTIST Bonnie Tyler COUNTRY UK COMPANY CBS Records PRICE 9.90 YEAR 1988


Ответ

Если вам не требуется специфический для класса XmlDocument функционал, то проще воспользоваться XDocument из пространства имен System.Xml.Linq. Это позволит получить более компактный код.
Для вывода на консоль в том виде, который вы указали есть три пути.
1. Рекурсивный обход дерева XML
Реализуется довольно просто:
static void Main(string[] args) { XElement doc = XElement.Load(@"H:\test.xml"); PrintElementV1(doc); Console.ReadKey(); }
static void PrintElementV1(XElement elem) { if (elem.Elements().Count() > 0) { Console.WriteLine(elem.Name); foreach (XElement e in elem.Elements()) { PrintElementV1(e); } } else { Console.WriteLine("{0}: {1}", elem.Name, elem.Value); } }
Но вставить в этот вод избирательную нумерацию конкретных элементов без "костылей" не выйдет. "Костыль" для нумерации может выглядеть так:
static void PrintElementV1(XElement elem, int num) { if (elem.Elements().Count() > 0) { Console.WriteLine("{0}. {1}", num, elem.Name); int i = 1; foreach (XElement e in elem.Elements()) { PrintElementV1(e, i++); } } else { Console.WriteLine("{0}: {1}", elem.Name, elem.Value); } }
При этом будут пронумерованы все элементы кроме тех, которые не содержат в себе других элементов.
2. Фиксированный обход дерева XML
С точки зрения дерева, рекурсия сохраняется, такова уж структура дерева, но если эта структура фиксирована и известна, то можно обойтись без рекурсивного вызова методов а использовать цепочку вызовов в цикле. Покажу на примере:
static void Main(string[] args) { XElement doc = XElement.Load(@"H:\test.xml"); Console.WriteLine(doc.Name); PrintCDList(doc); Console.ReadKey(); }
static void PrintCDList(XElement elem) { int i = 1; foreach (XElement e in elem.Elements()) { Console.WriteLine("{0}. {1}", i++, e.Name); PrintContent(e); } }
static void PrintContent(XElement elem) { foreach (XElement e in elem.Elements()) { Console.WriteLine("{0}: {1}", e.Name, e.Value); } }
как видите, рекурсия отсутствует, но если структура XML будет отличаться от заложенной в коде, "все превратится в тыкву" и будет давать неверные результаты.
3. Ручной парсинг
Можно выполнить всю работу руками, получив исходный текст XML в виде текста. Для этого можно воспользоваться любым известным вам способом получения текста из файла.
Далее к строке исходного XML текста применяем всевозможные регулярные выражения или другие известные вам способы преобразования строки до получения строки или массива строк нужного вида и выводим полученное.
Приводить код данного способа не стану, так как вариантов для подобного решения существует масса, а взглядов на то, как это сделать правильно еще больше. К тому же, я сильно сомневаюсь, что подобный вариант будет существенно производительнее чем два предыдущих, скорее наоборот.
Выбирайте какой вариант вам больше подходит =)
PS: Если важно использовать именно XmlDocument, пишите в комментарии, дополню соответствующим примером.

Вызов метода для неизвестного элемента WinForm

public void FunctionA(Object element) { element.Items.Clear(); }
Пример использования:
FunctionA(checkedListBox1);
В функцию FunctionA будут поступать аргументы только checkedListBox и comboBox, у обоих элементов есть метод .Items.Clear()
Как сделать чтобы это заработало ?


Ответ

public void FunctionA(IList aList) { aList.Clear(); }
FunctionA(checkedListBox1.Items); FunctionA(comboBox1.Items);
Update
Что делать если в случае добавления checkedListBox1, нужно по умолчанию чекбокс в положении cheked.
Ну нет чудес.
if (aList is CheckedListBox.ObjectCollection) { ((CheckedListBox.ObjectCollection)aList).Add(Text, true); } else { aList.Add(Text); }

PDO - исполнение запроса с избыточным массивом параметров

Tакой код работает
$info = array(); $info[':nik'] = trim($_POST['nik']); $info[':phone'] = trim($_POST['phone']); $info[':FIO'] = trim($_POST['FIO']); $info[':email'] = trim($_POST['email']);
$sql = "select count(*) from `punbb_users` where `email` = :email limit 1"; $count = $DB->getOne($sql, array(':email' => $info[':email']));
Но если заменить последнюю строку:
$count = $DB->getOne($sql, $info);
То уже ничего не работает.
Сама функция $DB->getOne() подготавливает и исполняет запрос через pdo
public function getOne($sql, $params = NULL) { if (is_null($params)) { return $this->pdo->query($sql)->fetchColumn(); } else { $stmt = $this->prepare($sql); $stmt->execute($params); return $stmt->fetchColumn(); } }
public function prepare($sql) { return $this->pdo->prepare($sql); }
Это происходит от того, что нельзя передавать массив с другими параметрами, когда нужен лишь один, или я что-то не так делаю?
Желательна еще и ссылка на документацию, если так делать нельзя.


Ответ

Да, количество параметров в запросе и в массиве, который передается методу prepare() должно совпадать, в противном случае, вам должна возвращаться следующая ошибка
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens

Как получить mac адреса роутеров? c#

На codeplex есть что-то похожее, но там нету получения mac адреса устройства. Как можно получить весь список имен и мак адресов роутеров (wifi точек)?


Ответ

BSSID (а также уровень сигнала в дБм) можно получить, вызвав метод GetNetworkBssList
// вывод MAC в виде ХХ:ХХ:ХХ:ХХ:ХХ:ХХ static string GetStringForBSSID(byte[] bssid) { var result = new StringBuilder();
result.Append(bssid[0].ToString("X2")); for (int i = 1; i < bssid.Length; ++i) { result.Append(":").Append(bssid[i].ToString("X2")); }
return result.ToString(); }
static string GetStringForSSID(Wlan.Dot11Ssid ssid) { return Encoding.ASCII.GetString(ssid.SSID, 0, (int)ssid.SSIDLength); }
public static void Main(string[] args) { var client = new WlanClient();
if (client.Interfaces.Length < 1) throw new InvalidOperationException("Wireless adapter not found.");
Console.WriteLine("SSID\t\t\tBSSID\t\t\tRSSI"); Console.WriteLine("-------------------------------------------------------");
WlanClient.WlanInterface nic = client.Interfaces[0]; foreach (Wlan.WlanAvailableNetwork network in nic.GetAvailableNetworkList(0)) { string ssid = GetStringForSSID(network.dot11Ssid);
Wlan.WlanBssEntry[] bssList = nic.GetNetworkBssList( network.dot11Ssid, network.dot11BssType, network.securityEnabled);
int rssi = 0; string bssid = ""; if (bssList.Length > 0) { rssi = bssList[0].rssi; bssid = GetStringForBSSID(bssList[0].dot11Bssid); }
Console.WriteLine("{0,-16}\t{1,-8}\t{2} dBm", ssid, bssid, rssi); } }

Можно ли протестировать в java зажата кнопка или нет?

Можно ли протестировать в java зажата кнопка или нет, например если я зажму кнопку W, то k=1, а если отожму то k=0? Если можно пример. Вот код моей кнопки:
if (ke.getCode().getName().equals("W")) { k = 1; }
switch (k) { case 1:// W gc.drawImage(fon, 0, 0, 1280, 720);
koy = koy - SPEED; gc.setFill(Color.BLACK); gc.fillOval(kox - 5, koy - 5, kord + 10, kord + 10);
gc.setFill(Color.YELLOWGREEN); gc.fillOval(kox, koy, kord, kord); for (int l = 0; l < 26; l++) { if (koy == prom1[l] - kord) { koy = koy + 720 + kord; } } break;}


Ответ

Да можно. Ловите ваш ивент на Scene,Layout-e:
setOnKeyPressed() - При ножатии кнопки.
setOnKeyReleased() - При отжатии кнопки.
А пишите это как то вот так:
scene.setOnKeyPressed(event -> { if(event.getCode() == KeyCode.W){ //do_something }
scene.setOnKeyReleased(event -> { if(event.getCode() == KeyCode.W){ //do_something } });

Как передать свой объект из jsp в контроллер

У меня есть User, в нем есть ссылка на Role, и например на странице editUser мне надо собрать объект User в контроллер spring MVC(в параметры контроллера добавляю User user), такие объекты как name(String)email(String), age(int) собираются в User нормально, а чтобы добавить туда Role мне надо редактируемого User'a достать из БД извлечь его роль и засетить в новый объект User и только потом делать update в hibernate.
Так вот вопрос можно ли как то spring'ом сразу User собрать вместе с Role из jsp страницы?
Пробовал указать поле в верстке
input type="hidden" name="role" value"${user.role}"
но тогда вообще контроллер не находит и редиректит на страницу 400.
P.S User добавляю из get-контроллера в jsp, тоесть переменные User можно достать в jsp


Ответ

Как по мне, на уровне клиента это невозможно.
Как вариант, тебе нужно сперва запросом отправить id нужного объекта, а потом используя id получить его.
Я бы сделал бы это вот так
html
... ... ... ...
Внутри метода*
.........@ModelAttribute("user") User user, @RequestParam("id") Integer id) { .... Role role = (Role) session.createQuery("from Role role where role.id=:id").setParameter("id", id).list().get(0); user.setRole(role); .... }

Регулярное выражение (-слово, слово- и -слово-)

Как сформулировать выражение, чтобы можно было запретить использования тире в данных местах относительно уникального слова
-слово, слово- и -слово-
Другими словами, регулярку, которая запретить любое нахождение тире относительно уникального слова:
перед словом, после слова и слово между двух тире
Спасибо заранее
Сам попытался, но никак
[^-]слово[^-]


Ответ

В регулярных выражениях для таких случаев есть специальные "не захватывающие" проверки.
(?

C# webbrowser как двигать скрол?

Столкнулся с такой проблемой. В webbrowser открывается страничка, в ней есть скрол. Как можео им управлять? Подвинуть вверх, вниз?


Ответ

Еще способы:
WebBrowser.Document.Window.ScrollTo(int x, int y); WebBrowser.Navigate("javascript:window.scroll(...);");

WCF служба, wsDualHttpBinding и 80 порт

При подключении к WCF службе вылетает exception, хотя в app.config конфиг явно указан не 80 порт:
An unhandled exception of type 'System.ServiceModel.AddressAlreadyInUseException' occurred in System.ServiceModel.dll Additional information: HTTP could not register URL http://+:80/Temporary_Listen_Addresses/c3e45f68-abf2-4847-95a6-cfd3f512fc54/ because TCP port 80 is being used by another application.
Самое странное, что на одном ПК вылетает exception, а на другом нет. В чем может быть проблема?
app.config клиента :

app.config сервер:


Ответ

Вы используете wsDualHttpBinding. В этом режиме клиент прослушивает некоторый адрес, где ожидает ответы от сервера. И вот этот-то адрес, который в конфиге вы не задавали, и находится на 80м порту по умолчанию!
Используйте атрибут clientBaseAddress для указания обратного адреса на клиенте:

Либо используйте другие способы соединения. Так, netTcpBinding - и без обратного адреса умеет передавать сообщения в обе стороны. Еще где-то в WCF есть поддержка веб-сокетов, но я не помню где.

Теперь почему может быть занят 80й порт на некоторых компьютерах. Скорее всего, это Skype, который использует этот порт по умолчанию:

Но, конечно же, не следует отбрасывать и вариант обычного веб-сервера, Apache, Nginx или Tomcat. А вот IIS с WCF "дружат", поскольку используют один и тот же HTTP.SYS.

Rust. Вызов метода у Arc

Читаю Rustbook и не понимаю некоторые вещи.
use std::sync::{Arc, Mutex}; use std::thread;
fn main() { let data = Arc::new(Mutex::new(vec![1u32, 2, 3])); for i in 0..3 { let data = data.clone(); //(1) thread::spawn(move || { let mut data = data.lock().unwrap(); //(2) data[i] += 1; }); } thread::sleep_ms(50); }
(1). Метод clone() возвращает тип self, т.е. Arc<_>. В этом можно убедиться, если явно написать тип:
let data: Arc>> = data.clone();
В связи с этим возникает вопрос: почему в (2) мы вызываем метод lock() так, если бы мы работали напрямую с Mutex? Все как в C++, но там у shared_ptr оператор -> перегружен за нас, а покопавшись в исходниках arc.rs я не увидел подобного или пропустил.
UPD
Спасибо Кнопкатык за наводку на Deref coercions. Для закрепления написал такой искусственный пример:
use std::ops::Deref;
#[derive(Debug)] struct Field { x: i32, }
impl Field{ fn print(&self){ println!("x = {}", self.x); } }
#[derive(Debug)] struct Example { x: Field, }
impl Deref for Example{ type Target = Field;
fn deref(&self) -> &Field{ &self.x } }
fn main() { let s = Example { x: Field { x: 5} }; s.print(); }
Структура Example не имеет имплементации метода print. Но если вспомнить универсальный синтаксис вызова функций, то
s.print();
можно заменить на:
Field::print(&s);
Следовательно, так как у нас есть реализация типажа Deref для Example, возвращающая &Field, то значения Example, если нужно, будут автоматически преобразовываться в &Field при разыменовании:
Field::print(&Example) -> dereference -> Field::print(&Field);
Код, как и предполагается, выведет:
x = 5


Ответ

Дело в механизме Deref coercions или "Преобразования при разыменовании". Arc реализует типаж Deref, значения &Arc будут автоматически преобразованы в &T, когда это необходимо. Метод lock(&self) Мютекса принимает &self, и когда мы пытаемся вызвать его с Arc
lock(&Arc)
срабатывает механизм Deref coercions
lock(&Mutex)
а &Mutex это и есть &self для метода lock.

Sidebar меню как сделать?

Как сделать sidebar меню так, как на этом сайте?
Чтобы три подпункта меню всегда были видны, а при нажатии на большой заголовок меню показывалось полностью.


Ответ

Через css предварительно скрываем все элементы, начиная с пятого .item:nth-child(+n+5) Скрываем и раскрываем все элементы, начиная от четвёртого $('.item').slice(4)
Видимо в css порядок начинается с 1, а в js с 0
$('.item').eq(0).click(function() { $(this).html() == '↓ список' ? $(this).html('↑ список') : $(this).html('↓ список'); $('.item').slice(4).slideToggle(); }); .item { list-style: none; background: #E0E4E8; padding: 2px 4px 2px 4px; cursor: pointer; } .item:hover { background: #F4F8FB; } .list { display: list-item; } #list { cursor: pointer; } .item:nth-child(+n+5) { display: none; }

  • ↓ список
  • item 1
  • item 2
  • item 3
  • item 4
  • item 5
  • item 6

Сортировать записи из таблицы mysql в определённом порядке

Имеется таблица mysql с записями, которые через php выводятся на страницу в определённом порядке, например: 128, 59, 70, 293, 19 и т.д. Каждая новая запись должна занимать определённое место в данном порядке (порядок записей определяю сам в зависимости от контента). Например, новая запись 476 должна быть вставлена между 59 и 70, т.е. образуется такой массив.
Сейчас я делаю это так: каждой записи даю некоторое число и в запросе указываю сортировку по этим числам. Но я думаю такой алгоритм не очень эффективен, тем более, что данные числа я прописываю вручную.
Есть идеи как можно сделать это по нормальному, не нагружая сильно сервер?


Ответ

На самом деле отдельное поле с идентификаторами задающими порядок - не такая плохая идея. Поле числовое, поэтому сортировка по нему осуществляется очень быстро, оно может быть проиндексировано, поэтому запрос может быть еще более ускорен и практически не зависеть по скорости от объема таблицы.
Заполнять это поле не обязательно вручную, можно прикрутить интерфейс, позволяющий перетаскивать позиции пользователю и пересчитывать это поле автоматически.
Альтернатив не так много и они уже не так эффективны. Например, MySQL-функция FIELD(), которая возвращает позицию вхождения первого аргумента в список, который задается оставшимися аргументами.
В качестве первого параметра передается поле id, а в качестве остальных аргументов используется список 128, 59, 70, 293, 19. Так как все не входящие в список значения будут получать значение 0, его лучше заменить на 65536
SELECT * FROM tbl ORDER BY IF(FIELD(id, 128, 59, 70, 293, 19) = 0, 65536, FIELD(id, 128, 59, 70, 293, 19))
или в качестве альтернативы можно обратить список и использовать ключевое слово DESC, тогда значения 0, возвращаемые функций FIELD() выстроятся в конец и их можно будет отсортировать по какому-то другому полю
SELECT * FROM tbl ORDER BY FIELD(id, 19, 293, 70, 59, 128) DESC, name;
Однако этот подход хуже, чем дополнительное поле, так как вычисления позиции осуществляются при выборки каждой строки, такое динамическое поле невозможно проиндексировать (по крайней мере в MySQL).
Лучше оставить отдельное поле для сортировки, однако рассмотреть возможность его автоматического заполнения. Например, по умолчанию присваивать ему максимальное значение + 1, т.е. размещать в конце, а при перетаскивании элемента, вычислять смещение и изменять (UPDATE) это поле у всех строк в интервале смещения.