Страницы

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

четверг, 9 апреля 2020 г.

Прочитать с середины файл без чтения его начала на Rust'е

#файлы #потоки_данных #filestream #rust #fstream

                    
let f = File::open("file").unwrap();
let reader = BufReader::new(f).seek(io::SeekFrom::Start(2));
for b in reader.iter().next() {
    println!("{}", b);
}


Выводит то, что находится внутри io::SeekFrom::Start, т.е. 2.
    


Ответы

Ответ 1



Какой-то странный цикл у вас. По идее должно быть как-то так: let f = File::open("file").unwrap(); let mut reader = BufReader::new(f); reader.seek(io::SeekFrom::Start(2)).unwrap(); for b in reader.bytes() { println!("{}", b); } Метод seek() возвращает Result, то есть новую позицию в файле. Он вызывается на &mut self, значит reader должен быть mut, иначе не заработает. Что делает ваш код: вы открываете файл и смещаете указатель на 2 байта, сохраняя Result в reader. Потом вы преобразовываете Result в итератор с помощью iter() и вызываете на итераторе next(), получаете Option, равный Some(2). А потом по опции итерируете (Option<_> реализует IntoIterator, так что этому типу можно итерировать). Итератор весело выдаёт один элемент — 2. Чтобы избежать подобных ошибок в будущем, внимательно читайте документацию на используемые трейты и типы: ни в трейте Read, ни в типе BufReader нет метода iter(), однако в Read есть метод bytes(), который вам был нужен. А вот метод Seek::seek возвращает Result. Кроме того стоит больше прочитать про интерфейс итераторов, так как вы, судя по всему, до конца не поняли эту идею, раз вызываете на итераторе метод next() явно.

Реализация синглтона с многократным освобождением ресурсов

#c_sharp #шаблоны_проектирования

                    
Как правильно реализовать многопоточный синглтон с возможностью в любой момент и
из любой нити освободить все занятые ресурсы и так чтобы при следующем запросе они
снова лениво разворачивались. 
    


Ответы

Ответ 1



А в чём проблема? Ну окружите весь доступ мьютексом. Поскольку вам нужна логика реинициализации, простое решение с Lazy-свойствами не проходит. public sealed class Singleton { // классическая реализация из статьи Jon Skeet'а // http://csharpindepth.com/articles/general/singleton.aspx private static readonly Lazy lazy = new Lazy(() => new Singleton()); public static Singleton Instance { get { return lazy.Value; } } private Singleton() { } /////////////////// ленивые свойства /////////////////// object accessMutex = new object(); string lazyProperty; public string LazyProperty { get { lock (accessMutex) return lazyProperty ?? (lazyProperty = CreateLazyProperty()); } } public void Reset() { lock (accessMutex) { lazyProperty = null; // обнулите остальные свойства, освободите IDisposable-ресурсы } } string CreateLazyProperty() { ... } }

Как вытащить данные из excel файла представленного в виде массива байтов?

#c_sharp #excel #sdk #openxml

                    
Добрый день!
Как я могу вытащить данные или скопировать sheet из excel-файла, представленного
в виде массива байтов, используя Open XML SDK?
    


Ответы

Ответ 1



Например, через MemoryStream и конструктор со стримом: byte[] buffer = ...; using (var ms = new MemoryStream(buffer)) { var document = PresentationDocument.Create( ms, PresentationDocumentType.Presentation, autoSave: true /* или false */); // работаем как обычно }

MonthCalendar реагирует на “пустые ячейки”

#c_sharp #visual_studio #winforms #calendar

                    




В visual studio есть стандартный контрол MonthCalendar.
По умолчанию контрол выглядит как на левой части картинки. 
На нем видно числа следующего месяца и их можно выделить и контрол переместится на
новый месяц.

Если в контроле установить calendar dimension равный 1,2 то контрол примет  вид как
на правой части картинки. Будет видно сразу два месяца. Но если начать выделять, то
происходит нелепица как показано на видео или в гифке. 

Происходит это потому что в пустых "ячейках" календаря есть дни следующего месяца,
но их не видно, т.к. следующий месяц показан полностью из-за calendar dimension. 

Как сделать так чтоб контрол не реагировал на пустых "ячейках", в которых есть данные
о следующем месяце, но их не видно?
    


Ответы

Ответ 1



С этим ничего сделать нельзя. MonthCalendar — это обёртка над системным элементом управления SysMonthCal32. Сам класс никакой особой логики не содержит, поведение реализовано на уровне операционной системы. А вот операционная система настолько глючная, что выделение так странно работает. Или, может быть, кто-то счёл, что это не баг а фича. Так или иначе, это норма. Вероятно, про этот элемент управления забыли давно и основательно. Сейчас модно использовать WPF, UWP и т. п., а WinForms — это легаси.

Определить значение элемента «спиральной матрицы» по его координатам

#java #алгоритм

                    
Недавно был вопрос об инициализации массива спиральной матрицей. Хотя предложенные
решения его решают, интересно решить эту задачу без использования памяти под массив,
а именно:


  Написать метод getNum(int s, int x, int y), который принимает три целых параметра
— размер квадратной матрицы (s) и координаты позиции в этой матрице (x, y от 0 до s-1)
и возвращает число от 1 до s*s, которое должно стоять в соответствующей ячейке «спиральной
матрицы» (сматывающейся от левого-верхнего угла к центру по часовой стрелке).


Тогда задача вывода данной матрицы на экран должна свестись к такому коду (никакой
массив не нужен):

for (int y = 0; y < s; y++) {
    for (int x = 0; x < s; x++) {
        System.out.printf("%4d", getNum(s, x, y));
    }
    System.out.println();
}


Кроме того можно вообще выводить огромные матрицы, в UI-окошке и скроллить мышкой,
быстро отрисовывая только видимую часть.

Как же реализовать такой метод?

Решения на других языках тоже принимаются.
    


Ответы

Ответ 1



Для начала переведём входные координаты x и y в систему координат относительно центра матрицы. Так как размер может быть чётным или нечётным, удвоим координаты, чтобы не возиться с половинками: x = 2 * x - s + 1; y = 2 * y - s + 1; Скажем, для матрицы 5×5 возможные значения x и y будут -4, -2, 0, 2, 4. А для матрицы 6×6 — -5, -3, -1, 1, 3, 5. Дальше определим, на каком квадрате от центра лежит текущая точка. Это просто максимум модуля обеих координат: int n = Math.max(Math.abs(x), Math.abs(y)); Скажем, для квадрата 5×5 значения будут такие: 4 4 4 4 *4 4 2 2 *2 4 4 2 *0 2 4 4 2 2 2 4 4 4 4 4 4 Заметим, что внутри текущего квадрата (n-1)*(n-1) записей. Попробуем определить, какое число должно быть на правой-верхней диагонали. Надо из квадрата s*s вычесть квадрат n*n и посмотреть, что получается. Оказывается, надо ещё n вычесть. Вот значения s*s-n*n-n для квадрата 5×5: 5 5 5 5 *5 5 19 19 *19 5 5 19 *25 19 5 5 19 19 19 5 5 5 5 5 5 Ура, диагональ получили. С чётной стороной это тоже верно. Теперь посчитаем расстояние от этой диагонали с учётом знака: int p = (y + x) / 2; Прибавим это расстояние к нашему s*s - n*n - n, получим: 1 2 3 4 5 2 17 18 19 6 3 18 25 20 7 4 19 20 21 8 5 6 7 8 9 Отлично, теперь весь правый-верхний треугольник мы правильно выдаём. Чтобы починить левый-нижний, надо для него заменить p на 2*n-p. Точка лежит в левом-нижнем треугольнике, если x < y: if (x < y) p = 2 * n - p; Вот полный код: public static int getNum(int s, int x, int y) { x = 2 * x - s + 1; y = 2 * y - s + 1; int n = Math.max(Math.abs(x), Math.abs(y)); int p = (x + y) / 2; if (x < y) p = 2 * n - p; return s * s - n * n - n + p; }

Ответ 2



Вот чистое C без рекурсии, массивов и с двумя параметрами. Самое элегантное решение, что мне удалось получить. Левый верхний угол, индексация с нуля. Вход: 0 1 2 3 4 5 6 7 8 Выход: 0 1 2 7 8 3 6 5 4 Правда я его так и не проверил, могут быть ошибки, но идея состоит в том, чтобы просто использовать явную формулу: uint32_t spiral(uint32_t size, uint32_t index) { int x = 2 * (index % size) - size; int y = 2 * (index / size) - size; return (abs(x)>abs(y)) ? ((x>0) ? (4*x*x-3*x+y) : (4*x*x-x-y)) : ((y>0) ? (4*y*y-y-x) : (4*y*y-3*y+x)); }

Нестандартная сериализация/десериализация при помощи newtonsoft json

#c_sharp #json #serialize

                    
Есть следующие классы:

public sealed class User
{
    public int Id { get; set; }
    public Schema Extensions { get; set; }  
}

public sealed class UserProperty
{
    public string Id { get; set; }
    public object Value { get; set; }
}

public sealed class Schema
{
    public string Name { get; set; }
    public List Properties { get; set; } 
}


Задается вот так:

 var user = new User
 {
    Id = 1,
    Extensions = new Schema
    {
      Name = "urn:scim:schemas:custom:1.0",
      Properties = new List { new UserProperty { Id = "A", Value = 1} }

    }
 };


Необходимо получить json следующего вида:

{
  "Id": 1,
  "urn:scim:schemas:custom:1.0": {
     "A": 1
  }
}


Как это можно сделать при помощи библиотеки newtonsoft? И соответственно потом десериализовать
в структуры, описанные выше? 
    


Ответы

Ответ 1



Вам нужен JsonExtensionDataAttribute. Но тут есть ограничение - насколько я понимаю, он может быть только типа, реализующего IDictionary.

Cast оператор и шаблонные функции

#cpp #шаблоны_с++

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

template
struct Usefull;

template
struct Helper {
    Helper(T i) : v(i)
    {}

    T v;

    operator Usefull()
    {
        return Usefull(v);
    }
};

template
struct Usefull {
    Usefull(T i) : h(i)
    {}

    Helper h;
    void print()
    {
        std::cout << h.v << std::endl;
    }
};

template
void foo(Usefull b)
{
    b.print();  
}


И я хочу использовать это вот так:

int main()
{
    Usefull x(42);
    foo(x.h);
}


Но возникает ошибка компиляции: 

template argument deduction/substitution failed: 
'Helper' is not derived from 'Usefull'


Использовать static_cast> не желательно, менять или перегружать foo
тоже не охота.
Есть ли какие-то еще способы заставить Helper хорошо и неявно преобразовываться
в Useful? 

То есть пользователь не должен знать с чем он работает на самом деле, Useful и Helper
для него должны вести себя одинаково. Может здесь можно использовать наследование,
но я не приложу ума как это организовать.
    


Ответы

Ответ 1



Согласно примечанию к параграфу №4 в разделе 14.8.2.1 Deducing template arguments from a function call стандарта C++ [ Note: as specified in 14.8.1, implicit conversions will be performed on a function argument to convert it to the type of the corresponding function parameter if the parameter contains no template-parameters that participate in template argument deduction. Such conversions are also allowed, in addition to the ones described in the preceding list. —end note ] В вашем случае соответствующий параметр функции содержит шаблонный параметр, который участвует в выведении шаблонного аргумента. Поэтому вам придется явно указать шаблонный аргумент или явно использовать приведение типов. Например Usefull x(42); foo(x.h); foo( static_cast>( x.h ));

MySQL ORDER BY приближенное значение

#php #mysql

                    
Доброго времени суток!
Сразу приведу пример чтобы было понятно.
На сайте стандартный поиск сортирует по title (названию новости).
У нас есть например 2 новости "семь" и "восемь"
и если ввести "семь" то выведет в первую очередь "восемь", т.к. у нас сортировка
по алфавиту.
Как написать поиск более точный?
PHP
    


Ответы

Ответ 1



Если конкретно надо вот прям сначала те которые начинаются, а потом которые только содержат, то WHERE title LIKE 'семь%' ORDER BY title UNION SELECT ... WHERE title LIKE '%семь%' ORDER BY title Но вообще то что тебе нужно называется полнотекстовый поиск.

Ответ 2



попробуйте так SELECT title, CONCAT(' ', title) as title_ext FROM table WHERE title like '%семь%' ORDER BY CONCAT(' ', title)

Подмена базового класса в сложившейся архитектуре классов

#c_sharp #шаблоны_проектирования

                    
Имеется базовый класс (предположим, Window), у которого огромное число классов-потомков
(BlackWindow, TransperentWindow, ...).

Предположим, что я хочу добавить в архитектуру класс BorderedWindow, который перегружает
пару виртуальных функций родительского класса Window. И далее я хочу, чтобы все имеющиеся
классы-потомки могли создаваться как от Window, так и от BorderedWindow.

Проблему можно проиллюстрировать следующим кодом:

class Window
{
    public virtual Rectangle ClientArea()
    {
        return new Rectangle(0, 0, 100, 50);
    }
}

class BlackWindow : Window
{
    public BlackWindow(Window window) { ... }
}

class BorderedWindow : Window
{
    public overide Rectangle ClientArea()
    {
        return new Rectangle(5, 5, 110, 60);
    }
}

Window window = new Window();
BorderedWindow borderedWindow = new BorderedWindow();
new BlackWindow(window).ClientArea();                // Rectangle(0, 0, 100, 50), ОК
new BlackWindow(borderedWindow).ClientArea();        // Rectangle(0, 0, 100, 50), FAIL!


В целом, здесь можно применить паттерн Декоратор. Но этого делать не хочется, так
как последуют существенные изменения классов-потомков. Придётся для каждой функции
класса Window писать функцию-"обёртку" в каждом классе-наследнике. Для десятка функций
и десятка классов объём кода вырастает драматически.

Как можно исправить ситуацию?
    


Ответы

Ответ 1



Почему бы тогда не «Стратегия»? Вместо довольно неудобного наследования переходите на прогрессивную композицию. Пусть любой из классов получает ClientStrategy как часть конструктора. interface IClientAreaStrategy { Rectangle ClientArea { get; } } class DefaultClientAreaStrategy : IClientAreaStrategy { Rectangle clientArea = new Rectangle(0, 0, 100, 50); public Rectangle ClientArea { get { return clientArea; } } } class BorderedClientAreaStrategy : IClientAreaStrategy { Rectangle clientArea = new Rectangle(5, 5, 110, 60); public Rectangle ClientArea { get { return clientArea; } } } class Window { protected readonly IClientAreaStrategy clientAreaStrategy; public Rectangle ClientArea { get { return clientAreaStrategy.ClientArea; } } public Window(IClientAreaStrategy clientAreaStrategy) { this.clientAreaStrategy = clientAreaStrategy; } } class BlackWindow : Window { public BlackWindow(Window window) : base(window.ClientStrategy) { // ... } } (Кстати, у нужно ли наследование для BlackWindow? Возможно, вам снова нужна композиция?) Для конкретно этого случая вам не нужен целый интерфейс IClientAreaStrategy, а просто Func или даже просто Rectangle. Но в более сложном случае понадобится интерфейс.

Extjs Grid Panel выделить несколько строк

#extjs

                    
На Extjs Grid Panel надо  выделить несколько строк и отправить Ajax-ом. 

Умею отправлять по одному. 

Подскажите, как реализовать выделение нескольких строк?

Надо отслеживать нажатие Ctrl или есть другие способы?
    


Ответы

Ответ 1



При создании Ext.grid.Panel вам нужно переопределить создание selModel. К примеру в конструкторе панели вы определяете createSelModel: function() { var me = this; if (me.mode === 'SINGLE') me.mode = 'SINGL'; me.objs.selModel = Ext.create('Ext.selection.RowModel', { mode: me.mode }); }, в конфиге компонента selModel вы можете выбрать mode : "SINGLE"/"SIMPLE"/"MULTI". В вашем случае кокрас нужен "MULTI". Подробнее читайте здесь: http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.selection.Model

Как узнать позицию курсора мыши относительно экрана?

#c_sharp #wpf #position #cursor

                    
Как узнать позицию курсора по координатам (X, Y) относительно экрана, не прибегая
к средствам Windows.Forms?
    


Ответы

Ответ 1



В WPF есть класс Mouse у которого есть метод GetPosition. Чтобы получить позицию курсора относительно экрана можно использовать метод PointToScreen private void MainWindow_OnMouseMove(object sender, MouseEventArgs e) { var windowPosition = Mouse.GetPosition(this); var screenPosition = this.PointToScreen(windowPosition); this.Title = string.Format("{0} --- {1}", windowPosition, screenPosition); } Или как еще один вариант - использовать PInvoke.

Как осуществить поиск похожего текста в MySQL?

#mysql #база_данных #текст #выборка

                    
Дано: таблица с полями id и txt, где txt - небольшая статья, пост или комментарий,
содержащий HTML, примерный объем записи - 2-10 кб, всего записей 100к-1млн.

Нужно извлечь группы записей, в которых текст приблизительно похож, т.е. совпадать
процентов на 80-90, т.к. идентично равных строк в БД нет.

Позволяют ли существующие механизмы БД осуществить такую выборку, и как это сделать?

UPD: (очень близко) есть ли аналог пхп-шного similar_text() в mysql? Скорость выполнения
запроса не имеет значение.
    


Ответы

Ответ 1



Как было сказано выше, можно попробовать расстояние Левенштейна. Еще один пример реализации для mysql тут: http://www.artfulsoftware.com/infotree/qrytip.php?id=552 Можно сделать адаптированный вариант с этого примера: CREATE FUNCTION levenshtein( s1 text, s2 text ) RETURNS INT DETERMINISTIC BEGIN DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT; DECLARE s1_char CHAR; -- max strlen=255 DECLARE cv0, cv1 VARBINARY(10240); SET s1_len = CHAR_LENGTH(s1), s2_len = CHAR_LENGTH(s2), cv1 = 0x00, j = 1, i = 1, c = 0; IF s1 = s2 THEN RETURN 0; ELSEIF s1_len = 0 THEN RETURN s2_len; ELSEIF s2_len = 0 THEN RETURN s1_len; ELSE WHILE j <= s2_len DO SET cv1 = CONCAT(cv1, UNHEX(HEX(j))), j = j + 1; END WHILE; WHILE i <= s1_len DO SET s1_char = SUBSTRING(s1, i, 1), c = i, cv0 = UNHEX(HEX(i)), j = 1; WHILE j <= s2_len DO SET c = c + 1; IF s1_char = SUBSTRING(s2, j, 1) THEN SET cost = 0; ELSE SET cost = 1; END IF; SET c_temp = CONV(HEX(SUBSTRING(cv1, j, 1)), 16, 10) + cost; IF c > c_temp THEN SET c = c_temp; END IF; SET c_temp = CONV(HEX(SUBSTRING(cv1, j+1, 1)), 16, 10) + 1; IF c > c_temp THEN SET c = c_temp; END IF; SET cv0 = CONCAT(cv0, UNHEX(HEX(c))), j = j + 1; END WHILE; SET cv1 = cv0, i = i + 1; END WHILE; END IF; RETURN c; END; CREATE FUNCTION levenshtein_ratio( s1 text, s2 text ) RETURNS INT DETERMINISTIC BEGIN DECLARE s1_len, s2_len, max_len INT; SET s1_len = LENGTH(s1), s2_len = LENGTH(s2); IF s1_len > s2_len THEN SET max_len = s1_len; ELSE SET max_len = s2_len; END IF; RETURN ROUND((1 - LEVENSHTEIN(s1, s2) / max_len) * 100); END; Выбрать попарно похожие строки так: select t1.id, t1.txt, t2.id, t2.txt from table1 t1 join table2 t2 on t2.id <> t1.id and levenshtein_ratio(t1.txt, t2.txt) > 80 Как разбить результат выборки на группы, придется подумать. По работе, если кратко, то алгоритм считает количество замен/добавлений символов в текст, чтобы получить полностью схожие записи. Но главная проблема - алгоритм осуществляет посимволный перебор, что является довольно затратным. А теперь если учесть, что длина текста 2-10 кб и до 1 млн. записей, то база будет просто умирать от такой "аналитики" (а не забывайте, что главная задача базы - осуществлять хранение и доступ к данным, но никак не реализовывать сложные вычислительные алгоритмы). Поэтому я бы рекомендовал, пока не поздно, подумать над тем, чтобы вынести реализацию за пределы базы. Можно найти множество "быстрых" реализации вычисления расстояния Левенштейна практически на всех языках. При реализации предложил бы делать какую-то предварительную фильтрацию, например по длине текста, т.е. если длина не совпадает на 80%, то сравнение даже не проводить, т.к. даже на производительных машинах сравнение таких объемов текста уже будет заниматься ощутимое время.

Ответ 2



Вы можете решить данную задачу с помощью использования хранимых процедур. Например так: CREATE PROCEDURE dbo.spSimil_FirstNameLastName @str1 nvarchar(max), @threshold float AS SET NOCOUNT ON SELECT * FROM (SELECT dbo.fnSimil(@str1, Person.Person.FirstName + N' ' + Person.Person.LastName) AS Simil, * FROM Person.Person) AS T WHERE T.Simil >= @threshold ORDER BY T.Simil DESC; Процедура вызывается следующим образом: EXEC dbo.spSimil_FirstNameLastName N'John Adams', 0.75 Подробнее можно узнать тут: http://www.accessmvp.com/tomvanstiphout/simil.htm Для решения вашей задачи можно попробовать прибегнуть к расстояние Левенштейна: ссылка на реализацию для mysql: https://github.com/ifsnop/damlev

QByteArray во float

#qt #float

                    
Есть QByteArray, в котором лежат несколько float. Нужно их оттуда вынуть и записать
в соответствующие переменные. Пока единственным решением нашел копирование области
памяти с помощью memcpy:

float f1, f2;
memcpy(&f1, byteArray.data(), sizeof(float));
memcpy(&f2, byteArray.data()+sizeof(float), sizeof(float));


Если пытаться использовать QDataStream, то ничего путного не выходит, т.к. он пытается
считать не 4 байта, а 8. Какие решения еще можно найти?
    


Ответы

Ответ 1



Используйте класс QDataStream и setFloatingPointPrecision(). QByteArray arr; float f1, f2; QDataStream ds(&arr, QIODevice::ReadOnly); ds.setFloatingPointPrecision(QDataStream::SinglePrecision); ds >> f1 >> f2; Чтобы попеременно читать double и float, нужно переключать режим точности. QByteArray arr; float f1; double f2; QDataStream ds(&arr, QIODevice::ReadOnly); ds.setFloatingPointPrecision(QDataStream::SinglePrecision); ds >> f1; ds.setFloatingPointPrecision(QDataStream::DoublePrecision); ds >> f2; Либо можно читать "сырые" байты: QDataStream ds(&arr, QIODevice::ReadOnly); ds.readRawData(reinterpret_cast(&f1), sizeof(f1)); ds.readRawData(reinterpret_cast(&f2), sizeof(f2));

Выделить в текущей строке всё с первого непробельного символа до последнего

#vim

                    
Допустим, у меня есть строчка кода с отступом

         promocode.discount_amount


и курсор где-нибудь в районе слова discount_amount.

Чтобы выделить всё важное на строке, например, для заворачивания в скобки, я набираю

$v^

Уверен, есть более быстрое решение, но никак не могу его найти.
    


Ответы

Ответ 1



Поправка: чтобы переместиться к последнему непробельному символу, надо использовать g_, а не $. В вашем примере сработает viW (inner WORD, см. :help text-objects). Однако, в общем случае, когда в середине строки могут встречаться пробельные символы, это работать не будет. К сожалению в Vim нет стандартного text-object-а для того, что нам нужно. Тут нам на помощь придут mapping-и. Будем использовать для нашего «объекта» буквосочетание il (inner line). Никто не мешает использовать один символ, но тогда скорее придется пожертвовать соответствующей стандартной командой. Следующий mapping для visual mode позволяет сделать то, что нам нужно: :vnoremap il :normal! ^vg_ Теперь при нажатии vil будет выделена «важная» часть строки. Опционально: сейчас il работает только в visual mode. Можно заставить его работать со всеми командами Vim, которые ожидают на вход movement или text-object (d, y, c, и т.д.). Для этого используются mapping-и для Operator-pending mode (см. :help omap-info): " внимание, в правой части используется mapping il, который мы определили выше :onoremap il :normal vil Теперь, в частности, yil копирует «важную» часть строки, а dil — удаляет ее. Подробнее почитать, как и почему это работает можно в: Главе Operator-Pending Mappings (и след.) в книге Learn Vimscript the Hard Way Статье Creating new text objects Стандартном :help

Gitolite отказывается работать по ssh

#ubuntu #git

                    
Gitolite отказывается работать по ssh

Сервер


  -UBUNTU


Клиент


  -Win7


На сервере:


пользователь gitroot
установлен git на дефолтных настройках
установлен gitolite на дефолтных настройках
сгенерированы ключи ssh на дефолтных установках
файл sshd_config поправлен: 

раскоментированы строчки 



  RSAAuthentication yes
  
  PubkeyAuthentication yes



создан пользователь git
Копирован свой публичный ssh rsa ключ из домашней директории для настройки управления
репозиторием



  sudo cp ~/.ssh/id_rsa.pub /home/git/admin.pub



Заходим под пользователем git и заканчиваем настройку



  sudo su git 
  
  cd
  
  gl-setup admin.pub


На клиенте:


сгенерированы ключи через GitBash
скопирован публичный ключ на сервер через GitBash



  git clone ssh://git@server:/home/git/repositories/gitolite-admin.git


Спрашивает пароль для пользователя git, хотя не должно по инструкции. Что это может
быть? Ведь при создании пользователя git не нужно было вводить никаких паролей??

Если при создании пользователя git задать пароль то все отлично клонируется на локальную
машину. Только вот push выдает такое:


  $ git push origin master git@server password: Counting
  objects: 4, done. Delta compression using up to 4 threads. Compressing
  objects: 100% (3/3), done. Writing objects: 100% (4/4), 358 bytes | 0
  bytes/s, done. Total 4 (delta 1), reused 0 (delta 0) remote: ENV GL_RC
  not set remote: BEGIN failed--compilation aborted at hooks/update line
  20. remote: error: hook declined to update refs/heads/master To ssh://git@server:/home/git/repositories/gitolite-admin.git  !
  [remote rejected] master -> master (hook declined) error: failed to
  push some refs to
  'ssh://git@server:/home/git/repositories/gitolite-admin.git'

    


Ответы

Ответ 1



командой gl-setup /путь/к/файлу/с/публичным/ключом, выполненной от имени пользователя git, вы «настроили» этого пользователя на обслуживание инфраструктуры gitolite (которая этой же командой создана в домашнем каталоге этого пользователя). изначально инфраструктура содержит всего один репозиторий gitolite-admin, через который и осуществляется управление: создание и удаление репозиториев, назначение прав доступа к ним и т.п. публичный ключ, который вы передали параметром программе gl-setup, назначен при этом «административным». при помощи секретной части этого ключа теперь можно склонировать репозиторий gitolite-admin, и, внеся в него изменения (например, добавив в файл conf/gitolite.conf описание нового репозитория), «запушить» эти изменения обратно (что приведёт к созданию того самого нового репозитория). где «взять» эту секретную часть? там же, где вы «взяли» публичную: вы упомянули команду sudo cp ~/.ssh/id_rsa.pub /home/git/admin.pub, которую выполнили от имени какого-то пользователя. вот в домашнем каталоге этого неназванного пользователя и находится секретная часть ключа. в файле: ~/.ssh/id_rsa что же дальше делать? там же, на сервере, от имени того самого пользователя, чьей публичной частью ключа вы воспользовались при настройке gitolite, сделайте клон репозитория gitolite-admin: $ cd $ git clone git@server:gitolite-admin $ cd gitolite-admin и дальше управляйте gitolite-ом по инструкции. например, если вам надо дать административные полномочия пользователю, владеющему другой парой из публичного и секретного ключа, то: скопируйте новый публичный ключ в каталог keydir под именем, например, admin2.pub. добавьте (через пробел) admin2 в конец строки, начинающейся с @adm = в файле conf/gitolite.conf (это так группа adm описана). добавьте эти файлы в index: $ git add conf/gitolite.conf keydir/admin2.pub сделайте commit: $ git commit -m 'добавлен ключ admin2 в группу adm' отправьте изменения gitolite-у: $ git push p.s. а доступ по паролю к gitolite-у невозможен. только по ключу. потому у вас и ошибка происходит. дополнение про путь к репозиторию для правильного обращения к репозиториям, управляемым инфраструктурой gitolite, надо указывать лишь их имена. на приведённом примере — не: $ git clone ssh://git@server:/home/git/repositories/gitolite-admin.git а: $ git clone git@server:gitolite-admin

Отображение ExpandedListView в Fragment

#java #android #android_fragment

                    
При добавлении списка типа ExpandedListView в фрагмент цвет текста элементов этого
списка устанавливается белым и, естественно, на белом фоне список почти не видно:

 

Попробовал добавить этот же список в активити, все отобразилось как надо:



Единственный выход(пока что) - смена цвета бекграунда списка(или лейаута,в котором
находится список). Но все же хотелось бы добиться отображения как на втором скриншоте.
Заранее спасибо!

Код лейаута, в котором находится список:

    
    
    
        
        
    



Код фрагмента:

public class ExercisesFragment extends Fragment{

    ExpandableListView elvMain;
    ExercisesAdapter EA;
    SimpleExpandableListAdapter adapter;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
        final View rootView = inflater.inflate(R.layout.exercises_fragment, container,
false);

        EA = new ExercisesAdapter(getActivity());
        adapter = EA.getAdapter();

        elvMain = (ExpandableListView) rootView.findViewById(R.id.elvMain);

        //elvMain.setBackgroundColor(getResources().getColor(R.color.black));
        elvMain.setAdapter(adapter);

        return rootView;
    }
}


Код ExercisesAdapter:

public class ExercisesAdapter {

    final String ATTR_GROUP_NAME= "groupName";
    final String ATTR_EXERC_NAME= "exerName";


    // названия групп упражнений
    String[] groups = new String[] {"Group 1", "Group 2", "Group 3", "Group 4","Group
5", "Group 6", "Group 7", "Group 8", "Group 9"};

    // названия упражнений
    String[] Group1 = new String[] {"Exercise 1", "Exercise 2", "Exercise 3", "Exercise
4", "Exercise 5"};
    String[] Group2 = new String[] {"Exercise 1", "Exercise 2", "Exercise 3", "Exercise
4", "Exercise 5"};
    String[] Group3 = new String[] {"Exercise 1", "Exercise 2", "Exercise 3", "Exercise
4", "Exercise 5"};
    String[] Group4 = new String[] {"Exercise 1", "Exercise 2", "Exercise 3", "Exercise
4", "Exercise 5"};
    String[] Group5 = new String[] {"Exercise 1", "Exercise 2", "Exercise 3", "Exercise
4", "Exercise 5"};
    String[] Group6 = new String[] {"Exercise 1", "Exercise 2", "Exercise 3", "Exercise
4", "Exercise 5"};
    String[] Group7 = new String[] {"Exercise 1", "Exercise 2", "Exercise 3", "Exercise
4", "Exercise 5"};
    String[] Group8 = new String[] {"Exercise 1", "Exercise 2", "Exercise 3", "Exercise
4", "Exercise 5"};
    String[] Group9 = new String[] {"Exercise 1", "Exercise 2", "Exercise 3", "Exercise
4", "Exercise 5"};

    // коллекция для групп
    ArrayList> groupData;

    // коллекция для элементов одной группы
    ArrayList> childDataItem;

    // общая коллекция для коллекций элементов
    ArrayList>> childData;
    // в итоге получится childData = ArrayList

    // список аттрибутов группы или элемента
    Map m;

    Context ctx;

    ExercisesAdapter(Context _ctx) {ctx = _ctx;}

    SimpleExpandableListAdapter adapter;

    SimpleExpandableListAdapter getAdapter() {

        // заполняем коллекцию групп из массива с названиями групп
        groupData = new ArrayList>();
        for (String group : groups) {
            // заполняем список аттрибутов для каждой группы
            m = new HashMap();
            m.put(ATTR_GROUP_NAME, group); // имя группы
            groupData.add(m);
        }

        // список атрибутов групп для чтения
        String groupFrom[] = new String[] {ATTR_GROUP_NAME};
        // список ID view-элементов, в которые будет помещены аттрибуты групп
        int groupTo[] = new int[] {android.R.id.text1};

        // создаем коллекцию для коллекций элементов
        childData = new ArrayList>>();

        add(childData, Group1);
        add(childData, Group2);
        add(childData, Group3);
        add(childData, Group4);
        add(childData, Group5);
        add(childData, Group6);
        add(childData, Group7);
        add(childData, Group8);
        add(childData, Group9);

        // список аттрибутов элементов для чтения
        String childFrom[] = new String[] {ATTR_EXERC_NAME};
        // список ID view-элементов, в которые будет помещены аттрибуты элементов
        int childTo[] = new int[] {android.R.id.text1};

        adapter = new SimpleExpandableListAdapter(
                ctx,
                groupData,
                android.R.layout.simple_expandable_list_item_1,
                groupFrom,
                groupTo,
                childData,
                android.R.layout.simple_list_item_1,
                childFrom,
                childTo);

        return adapter;
    }

    public ArrayList>> add(ArrayList>> childData, String[] Group ){

        // создаем коллекцию элементов для первой группы
        childDataItem = new ArrayList>();
        // заполняем список аттрибутов для каждого элемента
        for (String exercise : Group) {
            m = new HashMap();
            m.put(ATTR_EXERC_NAME, exercise); // название упражнения
            childDataItem.add(m);
        }
        // добавляем в коллекцию коллекций
        childData.add(childDataItem);

        return childData;
    }
}

    


Ответы

Ответ 1



Задайте стиль для эелементов списка. У вас видимо textColorPrimary задан белым, вот и элементы списка с белым текстом. Как задать - стоит уже погуглить. По-другому вы не научитесь решать подобные проблемы

Ответ 2



Цвет текста по всей видимости наследуется от стиля, который у Вас определен в styles.xml Как вариант решения могу посоветовать указать в адаптере свою разметку adapter = new SimpleExpandableListAdapter( ctx, groupData, R.layout.my_expandable_list_item_1, groupFrom, groupTo, childData, R.layout.my_list_item_1, childFrom, childTo); А в ней уже менять все что душе угодно.

Ответ 3



У меня при добавлении ExpandedListView в Активити экстендс эктионБар, тоже цвет шрифта начинал сливатся с белым фоном, просто сменил разметку как советует ermak0ff Добавил my_expandable_list_item_1 и my_list_item_1 в папку layout, Там очень внимательным надо быть, во первых разметка как то не хотела через ctrl-v ctrl-c вставать, пришлось потихоньку со встреной разметки android.R.layout.simple_expandable_list_item_1 брать вьюшку и строить свои и как то все встало. Во вторых все ссылки правильно задать android.R.layout менять на R.layout там в коде эти ссылки не единыжды встречаются. В общем разметка заработала, цвет шрифта поменял.

Сделать несворачивающееся окно (по Win+D) [not topmost]

#winapi

                    
Чисто WinAPI, язык не принципиален.

Ситуация такая: делаю окно, оно НЕ topmost, и оно должно оставаться на экране при
нажатии Win+M и Win+D. Сейчас проверяю на Win7, но должно работать для любой.
Win+M вроде победил, а вот со вторым... Не могу понять, как вообще работает Win+D
- окну не приходят сообщения, которые я логически ожидал при сворачивании/перемещении.
А если как-то и получается заметить что свернули - не выходит запретить сворачивание.
Есть стандартная программа, которая имеет нужное поведение, но Spy++ вообще не может
ничего в ней отловить, даже под админом (первый раз такое увидел).

Проблема, что при нажатии Win+D окна пропадают (сворачиваются). А не должны. Кто-то
сталкивался с вопросом?

P.S. Возможно следует использовать какие-то новые интерфейсы оболочки Shell или DWM,
но никак не найду какие. :(
    


Ответы

Ответ 1



Надо изменить родительское окно, чтобы оно принадлежало Рабочему столу. Также может понадобиться предварительно отключить его отображение на панели задач. SetWindowLongPtr Me.hWnd, GWLP_HWNDPARENT, &H800F0 Где &H800F0 - это хэндл рабочего стола. Обращаю внимание, что вариант SetParent Me.hWnd, &H800F0 не годится, поскольку он делает окно частью рабочего стола, и любые (даже неактивные) окна будут отображаться поверх него. PS: Проверял на VB6, пришлось ещё в дизайнере формы выставить ShowInTaskbar = False, в противном случае окно сворачивается. Хендл рабочего стола узнал при помощи Spy++.

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

#javascript #html #jquery #yandex_maps_api #мобильная_разработка

                    
Cкажем вот эта карта — Яндекс.Карты multiRoute.

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

Вообще, решил так


function init() {
  var myMap = new ymaps.Map('map', {
    center: [55.76, 37.64],
    zoom: 10
  })
myMap.behaviors.disable('scrollZoom');
myMap.behaviors.disable('drag');
}

Но, вопрос остаётся: как отключить эту возможность только на мобильных устройствах, а на desktop — оставить?


Ответы

Ответ 1



Вот здесь подробно об этом - map.behavior.Manager function init() { var myMap = new ymaps.Map('map', { center: [55.76, 37.64], zoom: 10, behaviors: ["drag", "dblClickZoom", "rightMouseButtonMagnifier", "multiTouch"] }), /** * Создание мультимаршрута. * @param {Object} model Модель маршрута. Задается объектом с полями: referencePoints и params. * referencePoints - описание опорных точек мультимаршрута (обязательное поле); * params - параметры мультимаршрута. * @param {Object} [options] Опции маршрута. * @see http://api.yandex.ru/maps/doc/jsapi/2.1/ref/reference/multiRouter.MultiRoute.xml */ multiRoute1 = new ymaps.multiRouter.MultiRoute({ referencePoints: [ "Москва, метро Речной вокзал", "Москва, метро Водный стадион", ] }, { // Радиус транзитных точек на маршруте. viaPointIconRadius: 10, // Радиус точечных маркеров в путевых точках. pinIconRadius: 10, wayPointStartIconColor: "#80C257", wayPointFinishIconColor: "#8470FF", wayPointIconColor: "black", routeStrokeWidth: 2, routeActiveStrokeWidth: 6, routeStrokeColor: "000088", routeActiveStrokeColor: "#FF4500", pinIconFillColor: "#BFEFFF", viaPointIconFillColor: "#FFD39B", transportMarkerIconColor: "#FFE4E1" }), multiRoute2 = new ymaps.multiRouter.MultiRoute({ referencePoints: [ "Москва, метро Войковская", "Москва, метро Сокол" ] }, { routeStrokeWidth: 2, routeActiveStrokeWidth: 4, routeStrokeColor: "000088", routeActiveStrokeColor: "#66CDAA" }), buttonRoute1 = new ymaps.control.Button({ data: { content: "Первый маршрут" }, options: { maxWidth: 300 } }), buttonRoute2 = new ymaps.control.Button({ data: { content: "Второй маршрут" }, options: { maxWidth: 300 } }); myMap.controls.add(buttonRoute2); myMap.controls.add(buttonRoute1); myMap.geoObjects.add(multiRoute1); myMap.geoObjects.add(multiRoute2); buttonRoute1.events.add('select', function () { if (buttonRoute2.isSelected()) { buttonRoute2.deselect(); } myMap.setBounds(multiRoute1.getBounds()); }); buttonRoute2.events.add('select', function () { if (buttonRoute1.isSelected()) { buttonRoute1.deselect(); } myMap.setBounds(multiRoute2.getBounds()); }); multiRoute.model.events.add("requestsuccess", function () { var wayPoints = multiRoute1.getWayPoints(); wayPoints.get(0).properties.set('name', 'текст'); //Для метро Речной Вокзал }); } ymaps.ready(init); body { height: 100%; } #map { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }


Ответ 2



var isMobile = { Android: function() {return navigator.userAgent.match(/Android/i);}, BlackBerry: function() {return navigator.userAgent.match(/BlackBerry/i);}, iOS: function() {return navigator.userAgent.match(/iPhone|iPad|iPod/i);}, Opera: function() {return navigator.userAgent.match(/Opera Mini/i);}, Windows: function() {return navigator.userAgent.match(/IEMobile/i);}, any: function() { return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows()); } }; // после вызова карты if(isMobile.any()){ myMap.behaviors.disable('scrollZoom'); myMap.behaviors.disable('drag'); }

Ответ 3



В принципе, вот неплохая статья на эту тему. Там с помощью несложного скрипта и дива-обёртки данная проблема решается в несколько строк кода: https://blog.lisogorsky.ru/ignor-scroll-iframe-maps Если в двух словах, то: оборачиваем iframe в div с определённым классом, либо идентификатором. Для iframe указываем через css свойство pointr-events со значением none. Затем по клику на обёрточный div с помощью несложного JavaScript убираем свойство pointr-events

Ответ 4



Вообще, решил так map.behaviors.disable('scrollZoom'); map.behaviors.disable('drag'); Но, вопрос остается: как отключить эту возможность только на мобильных устройствах, а на десктоп оставить?

Ответ 5



Проще всего сгенерить карту через конструктор карт, и добавить флаг scroll=false, таким образом скролл (масштабирование) будет отключено. Пример:

Как получить содержимое страницы, которая грузится через AJAX?

#php #ajax #angularjs #http #парсер

                    
Получить содержимое страницы на PHP.
Раньше я делал это достаточно легко через file_get_contents( $url ). Но на одном
сайте список товаров грузится ajax-om, точнее ангуляром.
    То есть если открыть такую страницу в браузере, у вас будет крутиться лоадер
и через некоторе время появятся товары.

Функция file_get_contents( $url ) получает сырой код, то есть типа

{{tovari.name}}
Как получить обработанное( загруженное ) содержимое страницы?


Ответы

Ответ 1



Попробуйте подключиться через curl к нужной странице, должно сработать, например: $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_FAILONERROR, 1); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false); curl_setopt($curl, CURLOPT_POST, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($curl) curl_close($curl);

Ответ 2



Вам может помочь phantomjs. Через метод evaluate вы получите контекст загруженной страницы, а дальше можете либо качать всю страницу, либо весь арсенал JS селекторов у вас в руках. Пример взят с офф. сайта: var webPage = require('webpage'); var page = webPage.create(); page.open('http://m.bing.com', function(status) { var title = page.evaluate(function() { return document.title; }); console.log(title); phantom.exit(); });

Ответ 3



С помощью библиотеки CURL это возможно. Недавно сайт парсил где все на ajax и с библиотекой jQuery. Так если парсишь с помощью curl и потом выводим в браузер, то будет все криво, потому-что клиент в данный момент CURL(сервер), а не Вы. Кроссдоменный запрос не прокатит поэтому нужно взять к примеру библиотеку Simple HTMLDOM $curl = curl_init(); curl_setopt($curl, CURLOPT_FAILONERROR, 1); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // allow redirects curl_setopt($curl, CURLOPT_TIMEOUT, 10); // times out after 4s curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // return into a variable curl_setopt($curl, CURLOPT_URL, "https://ya.ru/"); curl_setopt($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 GTB6"); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($curl); Выводить $data не нужно. Всё, ваш клиент (сервер) получил страницу. Теперь скачиваем http://simplehtmldom.sourceforge.net/ И есть инструкция например здесь http://zubuntu.ru/php-simple-html-dom-parser/ То есть нам нужно продолжить так: $html=str_get_html($data); $result=$html->find(div.spisok span); //получаем массив Дальше его перебираем. foreach ($result as $one){ echo $one; //можем уже выводить то, что нашли } По такому принципу ищем данные, перебираем их. Важно точно определить "координаты" данных.

Ответ 4



Ну тут же все тоже самое загружаете инструмент разработчика , в любом браузере . В хроме и ему подобных (опера , яндекс , рамблер итд) он встроеный в мозиле firebug смотрите что грузится у вас после загрузки страницы , берете этот url подставляете свои параметры и тем же file_get_contents качаете контент

Ответ 5



В хроме я использую расширение https://chrome.google.com/webstore/detail/quick-source-viewer/cfmcghennfbpmhemnnfjhkdmnbidpanb?utm_source=chrome-app-launcher-info-dialog После загрузки страницы и отработки скриптов можно посмотреть результат со всеми изменениями.

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

#linux #изображения

                    
Есть ли возможность у findimagedupes сравнивать изображения в одной папке с другой?

Например, в одной папке 100 изображений, и в другой столько же. В первой папке есть
одно изображение, более, чем на 85%, похожее на одно изображение в другой папке.

Я пробовал делать так:

findimagedupes -t 85 "первая_папка/*"  "вторая_папка/*"


но дело в том, что он показывает совпадения, которые нашлись в первой папке и/или
во второй. А надо, чтобы сообщал, что «найдено изображение в папке первая_папка, которое
совпадает с изображением во вторая_папка»
    


Ответы

Ответ 1



можно в цикле перебрать все пары файлов: $ for f1 in первый_каталог/*; do \ for f2 in второй_каталог/*; do \ findimagedupes -t 85 $f1 $f2; done; done если же требуется, чтобы в выводимых строках пары файлов не были перемешаны (первым может идти файл то из первого, то из второго каталога), то можно каждую строку отсортировать, воспользовавшись возможностью программы findimagedupes передавать получаемые строки на обработку указанному скрипту (см. man findimagedupes): $ for f1 in первый_каталог/*; do \ for f2 in второй_каталог/*; do \ findimagedupes -t 85 -i \ 'VIEW(){ for f in "$@"; do echo $f; done | sort | xargs echo; }' -- \ $f1 $f2; done; done такой перебор каждого-с-каждым довольно ресурсоёмок («отпечатки»-fingerprints вычисляются при каждом запуске), поэтому для большей оптимальности следует либо дополнить нужной функциональностью саму программу, либо, вызывая её для всех файлов сразу, несколько усложнить скрипт, передаваемый программе опцией -i. обновление «усложнил» скрипт: #!/bin/bash d1=$(realpath $1) d2=$(realpath $2) e1=$(echo $d1 | sed 's,/,\\/,g') findimagedupes -t 85 -i 'VIEW() { n1=$(for f in "$@"; do echo $f; done \ | sed -n "/^'$e1'/{p;q}"); n2=$(for f in "$@"; do echo $f; done \ | grep "^'$d2'" | xargs echo); if [ -n "$n1" -a "$n2" ]; then \ for f in "$@"; do echo $f; done | sed -n "/^'$e1'/!{s|^|$n1 |;p}"; fi; \ }' $d1/* $d2/* вызывается он с двумя параметрами: первый_каталог второй_каталог (без каких-либо масок, просто пути к каталогам). для каждой строки, генерируемой программой, он оставляет только один файл из первого каталога (первый встретившийся), но разбивает её на несколько строк так, чтобы в каждой получившейся строке было только по одному файлу из второго каталога. например, строку dir1/file1 dir1/file2 dir2/file1 dir2/file2 он заменит на две строки: dir1/file1 dir2/file1 dir1/file1 dir2/file2 и, конечно, строки, в которых присутствуют только файлы из первого или только из второго каталога, игнорируются.

pc speaker c++ beep();

#cpp #linux

                    
Для winapi существует стандартная библиотека windows.h с функцией Beep().

Есть ли аналог в gnu/linux, или необходимо использовать сторонние библиотеки?
    


Ответы

Ответ 1



Если есть conio.h, можно воспользоваться putch('\a'); Про putchar рядом была тема, что не работает, но думаю, putch должен.

Ответ 2



Можно использовать возможности консоли линукс. Для этого нужно залогиниться в текстовый терминал. Далее использовать управляющие последовательности (в формате для printf): \033[10;%d] - установить частоту. \033[11;%d] - установить длительность в миллисекундах. \a - собственно выдать сигнал установленной частоты и длительности. Перед выдачей нового сигнала нужно подождать пока закончится текущий, иначе он будет прерван и сразу зазвучит новый. Может потребоваться загрузить модуль ядра для поддержки pc-speaker pcspkr или snd_pcsp и с помощью alsamixer включить всё, что касается speaker и beep. Код: #include #include void Beep(int Hz, int msec) { fprintf(stderr,"\033[10;%d]\033[11;%d]\a", Hz, msec); usleep(msec*1000); } int main(int argc, char* argv[]) { Beep(494, 250); Beep(523, 250); Beep(587, 500); Beep(523, 250); Beep(494, 250); Beep(440, 500); return 0; } Запускать необходимо из текстовой консоли или перенаправить вывод stderr на неё. Думаю в настоящее время более удобным является другой способ -- использовать одну из портируемых библиотек. Поэтому предлагаю реализацию Beep с помощью SDL в котором использовал идею алгоритма Брезенхема. Справедливости ради скажу, что для высоких частот звук консоли лучше. #include #include #include typedef struct { SDL_AudioSpec spec; int freq; int t; int err; int newfreq; int newt; Uint8 v; } udata_t; static udata_t uData; static void fill_audio(void *udata, Uint8 *stream, int len) { udata_t * const d= udata; while(len--) { if(!d->t) { if(d->newt) d->t = d->newt; d->freq = d->newfreq; d->newt = 0; } if(d->t) { d->t--; d->err += d->freq; if(d->err >= d->spec.freq) { d->err -= d->spec.freq*2; d->v= ~d->v; } } else if(!len) { SDL_PauseAudio(1); } *stream++ = d->v; } } void Beep(int Hz, int msec) { while(uData.newt) { usleep((uData.t*1000+uData.spec.freq-1)/uData.spec.freq*1000); } uData.newfreq= Hz*4; uData.newt= uData.spec.freq*msec/1000; if(!uData.t) SDL_PauseAudio(0); } void wait_audio() { while(uData.newt || uData.t) { usleep((uData.t*1000+uData.spec.freq-1)/uData.spec.freq*1000); } } void init_audio() { SDL_AudioSpec wanted; /* Set the audio format */ wanted.freq = 65535; wanted.format = AUDIO_U8; wanted.channels = 1; /* 1 = mono, 2 = stereo */ wanted.samples = 1024; /* Good low-latency value for callback */ wanted.callback = fill_audio; wanted.userdata = &uData; /* Open the audio device, forcing the desired format */ if ( SDL_OpenAudio(&wanted, &uData.spec) < 0 ) { fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError()); exit(1); } uData.err= uData.spec.freq; } int main(int argc, char* argv[]) { SDL_Init(SDL_INIT_AUDIO); init_audio(); Beep(494, 250); Beep(523, 250); Beep(587, 500); Beep(523, 250); Beep(494, 250); Beep(440, 500); wait_audio(); return 0; } Компиляция: gcc beepsdl.c `sdl2-config --cflags --libs` либо sdl-config вместо sdl2-config в зависимости от версии. Возможно потребуется поставить libsdl2-dev.

Странная ошибка в XAML: ошибка при конвертации типа при присваивании через StaticResource

#c_sharp #wpf #xaml

                    
Не знал как коротко описать суть проблемы.

Вот код xaml


    
        
    
    
        
    



Вот код c# класса LocalizedString

public class LocalizedString : IComparable, ICloneable, IEnumerable, IEquatable,
IEquatable
{
    public LocalizedString(string str)
    {
        OriginalString = str;
    }

    public LocalizedString()
    {
        OriginalString = "";
    }

    public string OriginalString { get; set; }

    public string LocalizeString
    {
        get
        {
            return InteractiveLocalizer.Localize(OriginalString);
        }
    }

    public override string ToString()
    {
        return LocalizeString;
    }

    public int CompareTo(object obj)
    {
        if (obj == null)
            return 1;
        var str = obj as string;
        if (str != null)
            return LocalizeString.CompareTo(str);
        var lstr = obj as LocalizedString;
        if (lstr != null)
            return LocalizeString.CompareTo(lstr.LocalizeString);
        throw new ArgumentException("LocalizedDtring: Bad type");
    }

    public object Clone()
    {
        return new LocalizedString(OriginalString);
    }

    public IEnumerator GetEnumerator()
    {
        return LocalizeString.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public bool Equals(string other)
    {
        return other == LocalizeString || other == OriginalString;
    }

    public bool Equals(LocalizedString other)
    {
        return OriginalString == other.OriginalString;
    }

    public static implicit operator LocalizedString(string v)
    {
        return new LocalizedString(v);
    }

    public static explicit operator String(LocalizedString ls)
    {
        return ls.LocalizeString;
    }
}


В данном случае LocalizedString ворачивает ту же самую строку, что и получает "qwe".
Я это и ожидал, но во время выполнения прога падает с исключением. Вот текст 


  "qwe" не является допустимым значением для свойства "Text".


Как так? 

Ошибка есть и во время компиляции (хоть она и позволяет запуститься приложению).
Вот ее текст


  Не удается применить объект типа "LocalizerLib.LocalizedString" к
  свойству, для которого требуется тип "System.String".


В классе определены операторы implict и explict. Чего еще не хватает, чтобы я мог
вместо string вставить свой тип?
    


Ответы

Ответ 1



XAML игноирирует операторы приведения типа (хоть явные, хоть неявные). Разнообразные конвертеры используются, например, для преобразования результатов биндинга. И даже в этом случае операторы не используются, предпочтение отдаётся ассоциированному TypeConverter (который, впрочем, по умолчанию поддерживает преобразование к строке и просто вызывает ToString). Однако при использовании ресурсов никакой конвертации не производится. Ваш код приводит к вызову: object res = new LocalizedString("foo"); fooTextBlock.Text = res; С очевидными последствиями. Могу предложить несколько путей: Вместо странных костылей с ресурсами можно воспользоваться расширениями разметки MarkupExtension. Метод ProvideValue может возвращать произвольный тип и даже учитывать, какому свойству какого объекта значение сейчас присваивается. Выглядеть это в XAML будет кратко и естественно: Продолжать городить костыли, но заставить XAML вызвать конвертеры: Вообще-то в WPF встроены средства для локализации, но кому до них дело... P. S. Код не тестировал, мог наврать.

Помогите разобраться с работой библиотеки Socket.IO-client Java

#java #android #сокет

                    
Хочу воспользоваться библиотекой  compile 'io.socket:socket.io-client:0.6.1', вот ссылка

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

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView status;
    private Button button;
    private Socket socket;
    {
        try {
            socket = IO.socket(Constants.CHAT_SERVER_URL);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        status = (TextView) findViewById(R.id.status);
        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(this);

        socket.connect();
        if (socket.connected()) {
            status.setText("Connected");
        } else {
            status.setText("Disconnected");
        }
    }


Я запускаю приложение, создается сокет, и на сервере срабатывает событие о том, что
клиент подключился. Это после строчки socket.connect(); А так же на сервере видно такие
логи:

Welcome to Server side
Waiting for a client...Client connected
Wait for messages
GET /socket.io/?EIO=3&transport=polling HTTP/1.1
User-Agent: Dalvik/1.4.0 (Linux; U; Android 2.3.7; Android SDK built for x86 Build/GINGERBREAD)
Host: 10.0.2.2:4444
Connection: Keep-Alive
Accept-Encoding: gzip


То есть, клиент действительно присоединился, и отправил какие то данные. Но дальше
непонятно. Первое это то, что не срабатывает мое условие:

if (socket.connected()) {
                status.setText("Connected");
            } else {
                status.setText("Disconnected");
            }


потому-что socket.connected() возвращает false. НО на стороне сервера показано, что
соединение установлено (если я закрою клиента, то и сервер говорит, что соединение
разорвано). Выходит, сервер видит, что клиент присоединен, но на клиенте говорится,
что соединения нет. И при попытке отправить сообщение на сервер:

@Override
    public void onClick(View v) {
        if (v.getId() == R.id.button) {
            socket.send("::::::::::::::::::::::::::::::::::::::::::::");
        }
    }


НИЧЕГО НЕ ПРОИСХОДИТ!

Как проверить или сделать, чтобы все заработало?

Мне просто нужно String  посылать на сервер и ВСЕ.

Вот код СЕРВЕРА:

public class Server {
    public static void main(String[] args) throws IOException {
        System.out.println("Welcome to Server side");
        BufferedReader in = null;
        PrintWriter out = null;

        ServerSocket servers = null;
        Socket fromclient = null;

        // create server socket
        try {
            servers = new ServerSocket(4444);
        } catch (IOException e) {
            System.out.println("Couldn't listen to port 4444");
            System.exit(-1);
        }

        try {
            System.out.print("Waiting for a client...");
            fromclient = servers.accept();
            System.out.println("Client connected");
        } catch (IOException e) {
            System.out.println("Can't accept");
            System.exit(-1);
        }

        in = new BufferedReader(new InputStreamReader(fromclient.getInputStream()));
        out = new PrintWriter(fromclient.getOutputStream(), true);
        String input, output;

        System.out.println("Wait for messages");
        while ((input = in.readLine()) != null) {
            System.out.println(input);
        }
        out.close();
        in.close();
        fromclient.close();
        servers.close();
    }
}

    


Ответы

Ответ 1



Во первых: Библиотека ассинхронная. Что это значит? То, что следующий код socket.connect(); if (socket.connected()) { status.setText("Connected"); } else { status.setText("Disconnected"); } Всегда войдет в else. потому, что socket.connect() - ассинхронный метод, выполняется в отдельном потоке, и если сразу же спросить у сокета socket.connected(), то он вернет false, потому, что connect не успел еще выполниться. Вместо этого надо повесить Listener перед тем, как вызвать connect: socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() { @Override public void call(Object... args) { //делаем все, что надо сделать после успешного коннекта } }) На счет остального - проверьте код сервера, мне показалось, что он должен обработать только первый коннект, и сразу завершиться.

Сложный список angular

#angularjs

                    
Есть массив типа = 

[
{"name":"Name","dep":"Dep1"},
{"name":"Name","dep":"Dep1"},
{"name":"Name","dep":"Dep1"},
{"name":"Name","dep":"Dep2"},
{"name":"Name","dep":"Dep3"},
]


Вопрос вот в чем. Как его правильно вывести с помощью ng-repeat или чего другого
если нужно каждый новый отдел в списке отделять разделителем?

Примерно так:

Dep1
Name
Name
Name
Dep2
Name
Name


Ответы

Ответ 1



function Controller($scope) { $scope.data = [ {"name":"Name","dep":"Dep1"}, {"name":"Name","dep":"Dep1"}, {"name":"Name","dep":"Dep1"}, {"name":"Name","dep":"Dep2"}, {"name":"Name","dep":"Dep3"} ]; } .is-other { border-top: 1px solid; } .is-other:first-child { border-top: none; }
  • {{item.dep}} -> {{item.name}}
function Controller($scope) { $scope.data = [ {"name":"Name","dep":"Dep1"}, {"name":"Name","dep":"Dep1"}, {"name":"Name","dep":"Dep1"}, {"name":"Name","dep":"Dep2"}, {"name":"Name","dep":"Dep3"} ]; } .dep { background: silver; }
{{item.dep}}
{{item.name}}


Как добавить сервисы Google в Android Studio, чтобы уменшить размер

#android #service

                    
Ребята хочу добавить AdMob, но не используя

compile 'com.google.android.gms:play-services:7.0.0'
Так  как из за этой команды вес приложение возрастает в 5 раз.
До этого весил 700кб, сейчас 5 мегабайт, Это слишком! Есть ли выход? Читал что какой
то можно ProGuard задействовать или в Gradle указать чисто для AdMob

Gradle

apply plugin: 'com.android.application'


    android {
    compileSdkVersion 23
    buildToolsVersion '23.0.1'
    defaultConfig {
        applicationId "com.eranewgames.animevideo"
        minSdkVersion 10
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors {
    }
}

repositories{
    flatDir{
        dirs 'libs'
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.mcxiaoke.volley:library:1.0.+'
    compile 'cz.msebera.android:httpclient:4.4.1.1'
    compile 'com.android.support:appcompat-v7:23.0.1'
}

    


Ответы

Ответ 1



Можно подключить отдельно только необходимую часть, полный список тут: https://developers.google.com/android/guides/setup Для AdMob достаточно com.google.android.gms:play-services-ads:8.1.0

Ответ 2



Обычно, перед созданием проекта в Android Studio, Вам должны предложить компоненты которые Вы хотите использовать в проекте. Начиная Play Games API, заканчивая Google Cast API. Попробуйте создать новый проект и вставить туда тот же код, но уже с выбранными компонентами.

Как реализовать переход между activity сохраняя сокет-соединение?

#java #android #клиент_сервер

                    
Пробую свои силы в клиент-серверах и наткнулся на такую проблему, если я хочу чтобы
на стороне клиента после подключения к серверу сменился Activity, но соединение не
потерялось, то как это реализовать понять не могу. 
Подключение клиента реализовывал в AsyncTask, который получается привязан к одному
Activity.

Для наглядного понимания вот пример: 

Допустим все клиенты сначала собираются в "комнате", а после того как все подключились
дается команда перейти на другое Activity с вопросами. Что-то типо онлайн викторины
где все стартуют одновременно.
    


Ответы

Ответ 1



есть один вариант. Запускать этот AsyncTask только один раз, и тогда можно будет обращаться к нему из любого Activity. public class DownloadWebPageTask extends AsyncTask { private static DownloadWebPageTask downloadWebPageTask; private Socket socket; // Это для соединения с сервером private DownloadWebPageTask(){ } public static synchronized DownloadWebPageTask getInstance( ) { if (downloadWebPageTask == null) downloadWebPageTask = new DownloadWebPageTask (); return downloadWebPageTask; } //... } использовать так (из любого Activity) DownloadWebPageTask downloadWebPageTask = DownloadWebPageTask.getInstance(); downloadWebPageTask.execute(a, b, c);

Очередь команд в консоли Linux

#linux #shell

                    
Предположим, что в данный момент в консоли уже выполняется какая-то команда. Она
занимает продолжительное время. Я хотел бы выполнить одну или несколько команд после
того, как завершится эта. Как это сделать?

Я знаю, что можно Ctrl + Z и bg, но это не совсем то. Нужно не в бэкграунд отправить
команду, а именно дождаться ее завершения.
    


Ответы

Ответ 1



используйте не bg (background), а fg (foreground), после которой добавьте нужную команду (команды): $ date; sleep 10 Fri Oct 2 10:45:04 MSK 2015 ^Z [1]+ Stopped sleep 10 $ fg; date sleep 10 Fri Oct 2 10:45:14 MSK 2015 fg и последующую команду можно связать и условиями, например: && или ||.

Открыть *.html файл во весь экран

#bat

                    
Пишется *.bat-файл для для запуска файла *.html на компьютере пользователя в браузере:

start index.html
exit


Как открывать его во весь экран?
    


Ответы

Ответ 1



start "" "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --kiosk --start-fullscreen -- file://D:/Temp/Supertemp/index.html Проверено на Google Chrome 45.0.2454.101 (Официальная сборка) m (64 бит)

Ответ 2



SendMessage App + WM_KEYDOWN + Virtual-Key Codes Окно браузера определяется по заголовку или по классу (тогда нужна программа типа Spy+). Дальше, с помощью SendMessage окну посылается сообщение WM_KEYDOWN(F11).

Как изменить размер div блока мышкой?

#javascript #html #jquery

                    
Как можно изменить высоту или ширину блока с помощью мышки, без библиотеки jquery-ui ?

Такой как здесь, только без jquery-ui, искал в интернете, но не смог найти.

Может есть какие-то другие библиотеки (размером 5-10 kb.) но не такие большие как
jquery-ui.
    


Ответы

Ответ 1



Если тебе нужно изменять ширину блока мышкой, вот пример. Если немножко изменить скрипт, я думаю что и высоту можно менять, только css код нужно доделать. $(document).ready(function() { var p = $(".pan1"); var d = $(".pan2"); var r = $("#resize"); var curr_width = p.width() var unlock = false; $(document).mousemove(function(e) { var change = curr_width + (e.clientX - curr_width); if(unlock) { if(change > 199) { $("#debug").text(e.clientX + " resize"); p.css("width", change); d.css("margin-left", change); } else { p.css("width", 200); d.css("margin-left", 200); } } }); r.mousedown(function(e) { curr_width = p.width(); unlock = true; r.css("background-color", "rgba(0, 0, 0, 0.2)"); }); $(document).mousedown(function(e) { if(unlock) { e.preventDefault(); } }); $(document).mouseup(function(e) { unlock = false; $("#debug").text(""); r.css("background-color", "rgba(0, 0, 0, 0.1)"); }); });

Ответ 2



В продвинутых браузерах есть специальное свойство: resize: none | both | horizontal | vertical Думаю, описания значений свойства не требуется. Нужно добавить, что для всех элементов, кроме textarea, свойство работает, только если у элемента установлено свойство overflow, в отличное от visible значение. Узнать, что это свойство есть, можно с помощью Modernizr, либо, просто проверить, есть ли у элемента это свойство: var div = document.createElement('div') if (typeof div.style.resize == 'undefined'){ console.log('нет'); } Если этого свойства нет, тогда уже можно использовать для этих целей JS.

Архитектура клиентского приложения Android для интернет магазина [закрыт]

#java #android #android_studio #rest

                            
             
                
                    
                        
                            Закрыт. Этот вопрос не по теме. Ответы на него в данный
момент не принимаются.
                            
                        
                    
                
            
                    
                
                        
                            
                        
                    
                        
                            Хотите улучшить этот вопрос? Переформулируйте вопрос,
чтобы он соответствовал тематике «Stack Overflow на русском».
                        
                        Закрыт 4 года назад.
                    
                
        

Есть интернет-магазин, нужно написать для него приложение, а точнее для работы с
его админкой. 
Основными функциями должны быть: 


добавление/изменение/удаление товаров
просмотр списка заказов
просмотр категорий/подкатегорий/товаров в виде дерева или каких-то
выпадающих списков


В качестве обмена данными с сервером используются REST API. В ответ сервер отдает JSON. 

Для выполнения запросов использую ApacheHttpClient (смотрю в сторону библиотеки Volley).
Для этого у меня создан класс со статическими переменными и методами для каждого запроса. 

На данном этапе интересует следующее:
в главном Активити есть кнопка "получить древо категорий" —» вызывается класс со
статическим методом для данного запроса —» в ответ получаю JSON-ом список категорий/
подкатегорий.

 

Коротко о работе приложения:
В MainActivity пользователь нажимает на кнопку найти товар по id -->> вызывается
 асинхронный запрос который обращается к статическому методу класса API.getProductById(String
id) -->> метод посылает нужный запрос на сервер  и получает от него ответ -->> далее
метод .getProductById(String id) отправляет ответ в MainActivity -->> в MainActivity
формируется интент с получеными данными и отправляется в нужную активити где и отображаются
данные для пользователя.

Вопросы: 

1) правильный ли я использую подход для выполнения запросов?

2) как поступить с полученным ответом, где и как его лучше хранить, возможно использовать БД?

3) каким способом можно отобразить данное дерево в Активити, что бы при нажатии на
товар я мог просмотреть о нем информацию?


КАТЕГОРИЯ

-подкатегория

-товар

-товар 

-подкатегория

-товар

-товар 


4) Какая иерархия классов должна присутствовать в подобном приложении.

5) Так же интересует: архитектура подобных приложений и какие средства используются
для их   реализации? Возможно какие-то примеры, литература...

P.S. Это первый опыт написания функционально приложения для Android с помощью Java,
буду рад любой информации!
    


Ответы

Ответ 1



Вы немного неверно строите архитектуру. Вам надо: Вынести обращения к серваку в отдельный сервис, который крутится в своем потоке - см. в сторону IntentService Полученые от Rest API данные надо складывать в SQLite БД, иначе если не будет коннекта или коннект будет медленный у вас ничего не будет показываться. Показывать нужно всегда данные из БД, причем посредством ContentProvider над этим БД. ContentProvider должен давать вам Cursor, а от курсора вы должны рисовать уже свои деревья/списки. В итоге получится так, что в фоне у вас будет крутиться сервис, который подсасывает данные из сервера и кладет в БД. Ну а поскольку над БД у вас будет развернут ContentProvider то все изменения которые будет вносить сервис в БД будет автоматом отображаться на UI. Для рисования списков в последнее время модным стало использование RecyclerView, он лучше себя ведет в тяжелых списках с картинками, правда и кода он требует чуток больше чем ListView. Как то так.

Как заменить блок текста в Perl?

#регулярные_выражения #perl

                    
К примеру есть такой кусок:


    TEXT_TO_REPLACE



как мне сделать замену TEXT_TO_REPLACE  с поиском по VARIABLE?
    


Ответы

Ответ 1



Ответ из комментариев от @Andrzej A. Filip $string =~ s/(\).*?(\<\/param\>)/\1$newtext\2/gis;

Как вывести все выбранные файлы?

#javascript #jquery

                    
Есть поле . Когда я выбираю несколько файлов, хочу получить
этот массив и вывести ниже списком пути файлов.

Есть такой код:

$('.add_photo_input').on('change', function() {
    var value = $('form input[type=file]').val();
    alert(value);
});


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


Ответы

Ответ 1



Имена всех выбранных файлов можно получить с помощью поля files (тип FileList) у , которое представляет собой список из File: $('form input[type=file]').on('change', function() { for (var i = 0; i < this.files.length; i++) { console.log(this.files[i].name); } });
Статья на MDN про работу с файлами.

Как отобразить по умолчанию форму для ввода комментариев (wordpress-сайт) на страницах записей произвольного типа?

#php #wordpress

                    
На вордпресс-сайте зарегистрирован произвольный тип записей: movies

Создан шаблон single-movies.php для отдельной страницы записи типа "movies"


Регистрация произвольного типа записей "movies" осуществлена с помощью кода (в файле
functions.php):

add_action('init', 'my_custom_init');

function my_custom_init() {
    // Регистрация произвольного типа записей "movies"
    $labels = array(
      'name' => 'Фильмы', // Основное название типа записи
      'singular_name' => 'Фильм', // отдельное название записи типа movies
      'add_new' => 'Добавить новый',
      'add_new_item' => 'Добавить новый Фильм',
      'edit_item' => 'Редактировать Фильм',
      'new_item' => 'Новый Фильм',
      'view_item' => 'Посмотреть Фильм',
      'search_items' => 'Найти Фильм',
      'not_found' => 'Фильмов не найдено',
      'not_found_in_trash' => 'В корзине Фильмов не найдено',
      'parent_item_colon' => '',
      'menu_name' => 'Фильмы'
    );
    $args = array(
      'labels' => $labels,
      'public' => true,
      'publicly_queryable' => true,
      'show_ui' => true,
      'show_in_menu' => true,
      'query_var' => true,
      'rewrite' => true,
      'capability_type' => 'post',
      'has_archive' => true,
      'hierarchical' => false,
      'menu_position' => null,
      'supports' => array('title', 'editor', 'thumbnail', 'excerpt', 'comments')
    );
    register_post_type('movies', $args);
    // Регистрация произвольного типа записей "movies"
    // end
  }
  // Добавляем фильтр, который изменит сообщение при публикации при изменении типа
записи movies
add_filter('post_updated_messages', 'movies_updated_messages');

function movies_updated_messages($messages) {
  global $post, $post_ID;

  $messages['movies'] = array(
    0 => '', // Не используется. Сообщения используются с индекса 1.
    1 => sprintf('movies обновлено. Посмотреть запись movies', esc_url(get_permalink($post_ID))),
    2 => 'Произвольное поле обновлено.',
    3 => 'Произвольное поле удалено.',
    4 => 'Запись movies обновлена.',
    /* %s: дата и время ревизии */
    5 => isset($_GET['revision']) ? sprintf('Запись movies восстановлена из ревизии
%s', wp_post_revision_title((int) $_GET['revision'], false)) : false,
    6 => sprintf('Запись movies опубликована. Перейти к записи movies', esc_url(get_permalink($post_ID))),
    7 => 'Запись movies сохранена.',
    8 => sprintf('Запись movies сохранена. Предпросмотр записи movies', esc_url(add_query_arg('preview',
'true', get_permalink($post_ID)))),
    9 => sprintf('Запись movies запланирована на: %1$s. Предпросмотр записи movies',
      // Как форматировать даты в PHP можно посмотреть тут: php.net/date
      date_i18n(__('M j, Y @ G:i'), strtotime($post - > post_date)), esc_url(get_permalink($post_ID))),
    10 => sprintf('Черновик записи movies обновлен. Предпросмотр записи movies',
esc_url(add_query_arg('preview', 'true', get_permalink($post_ID)))),
  );

  return $messages;
}

 // показ раздела "помощь" для типа записей movies
add_action('contextual_help', 'add_help_text', 10, 3);

function add_help_text($contextual_help, $screen_id, $screen) {
  //$contextual_help .= var_dump($screen); // используйте чтобы помочь определить
параметр $screen->id
  if ('movies' == $screen - > id) {
    $contextual_help =
      'Напоминалка при редактировании записи movies:
Указать нужную информацию.
Если нужно запланировать публикацию на будущее:
В блоке с кнопкой "опубликовать" нажмите редактировать дату.
Измените дату на нужную, будущую и подтвердите изменения кнопкой ниже "ОК".
';
  }
  elseif('edit-movies' == $screen - > id) {
    $contextual_help =
      'Это раздел помощи, показанный для типа записи movies';
  }
  return $contextual_help;
}


Для того, чтобы отобразить форму для ввода комментариев на странице записи произвольного
типа "movies", - в шаблоне single-movies.php добавляем стандартную функцию: 

В результате на отдельной странице записи типа "movies" вместо формы для ввода комментариев
- отображается текст: Обсуждение закрыто.
При этом в случае с записями стандартного типа - при использовании функции  - корректно отображается форма для ввода комментариев.
В админке во вкладке "Настройки обсуждения" - установлена галочка "Разрешить оставлять
комментарии на новые статьи"
Не установлена галочка "Автоматически закрывать обсуждение статей старше 14 дней"
Не установлена галочка "Пользователи должны быть зарегистрированы и авторизованы
для комментирования."
В админке непосредственно на странице редактирования записи произвольного типа -
отображается блок "Обсуждение". В нем есть два чекбокса: "Разрешить комментарии." ;
"Разрешить обратные ссылки и уведомления."


По умолчанию в чекбоксе "Разрешить комментарии." - галочка не поставлена. 

Если галочку поставить вручную - то тогда на странице записи произвольного типа "movies"
форма для ввода комментариев отобразится корректно. Однако форма для ввода комментариев
отобразится только на странице одной конкретной записи, для которой в админке вручную
поставили галочку в чекбоксе "Разрешить комментарии.", а не на всех страницах записей
произвольного типа "movies".

Вопрос: как сделать, чтобы в чекбоксе "Разрешить комментарии." галочка была бы по
умолчанию проставлена для всех записей произвольного типа "movies" ? (чтобы форма для
ввода комментариев отображалась бы по умолчанию на страницах записей произвольного типа?
    


Ответы

Ответ 1



Вам нужно обновить комментирование для постов в админке вот так: In SETTINGS > DISCUSSION uncheck the "Allow people to post comments on new articles" setting. Click "Save Changes" Now go back and re-check "Allow people to post comments on new articles" Click "Save Changes"

Стоит ли использовать спецсимволы в названиях таблиц/столбцов?

#mysql

                    
В мануале MySQL.Ru указано, что можно называть таблицы и столбцы с применением различных
символов (в более ранних версиях _, $). Стоит ли пользоваться или ограничиваться _?
    


Ответы

Ответ 1



Такие вещи должны оговариваться в "стандарте кодирования" конкретной команды разработчиков. Что для одних норма, то другим кошмар. Важно чтобы в одном проекте не было разнообразия в этом плане. В тех местах, где мне приходилось работать, для имен MySQL было принято ограничиваться нижним регистром латиницы + цифры и подчеркивание, snake-синтаксис. Вот примеры толковых соглашений об именах: http://anandarajpandey.com/2015/05/10/mysql-naming-coding-conventions-tips-on-mysql-database/ https://raw.githubusercontent.com/treffynnon/sqlstyle.guide/gh-pages/_includes/sqlstyle.guide.md

Ответ 2



Рекомендую использовать: нижний регистр, буквы, цифры и знак подчеркивания. Это наиболее часто встречающийся вариант в популярных FW. Для сообщества PHP+MySQL, имхо, уже стандарт. Чем меньше нестандартных решений, тем гибче и безопасней.

Android/Java. Как отобразить активити в форме Диалога?

#android #android_fragment #activity #style #dialogfragment

                    
Необходимо отобразить активити в форме Диалога.. чтобы задний фон расплывчат был..
А у самой активити должны быть скругленные углы. 

Вот как на рисунке:



Как это делается? Что и В каких методах или файлах прописывать?
    


Ответы

Ответ 1



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

Ответ 2



Создай layout для диалог-фрагмента. public class AddList extends DialogFragment implements Далее тебе нужно будет создать такой класс: public class extends DialogFragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { AlertDialog.Builder adb = new AlertDialog.Builder(getActivity()); rootView = inflater.inflate(R.layout., container); adb.setView(rootView); return rootView; } } И внутри прописать всё, что нужно. А внутри нужного активити прописать: dialog = new (); dialog.show(getSupportFragmentManager(), "");

Как отобразить сферу с объектами в WPF?

#c_sharp #wpf #xaml

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

Мне пока приходит в голову использовать ListBox с Canvas в качестве панели, где будет
отрисован круг, на котором будут отображены проекции объектов (то есть псевдо-сфера).
Для начала хочу просто отобразить сферу с меридианами, которую я смогу вращать. По
идее все должно получиться, но я даже не знаю с чего мне начать.

UPD:

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


Ответы

Ответ 1



Всё очень просто. Вам нужно перевести сферические координаты (широту, долготу радиус) в трёхмерные. Затем умножением на матрицу поворота повернуть в нужное положение. Затем спроектировать на плоскость, отбросив одну координату, например, Y. При этом точки с положительной координатой Y находятся на противоположной стороне и их надо отбросить. Полученную картинку из квадрата [-R, R] линейно отобразите в квадрат координат экрана. Для обработки выделения я обычно использую не индексы, а вот такую конструкцию: VM: class Objects : NotifyPropertyChangeImpl { ObservableCollection All { get; private set; } // стандартное INPC-свойство ObjectVM selectedObject; public ObjectVM SelectedObject { get { return selectedObject; } set { if (value == selectedObject) return; value = selectedObject; NotifyPropertyChange(); } } } XAML:

Sliding между Activity

#javascript #android

                    
Как сделать переключение между активити при помощи слайдинга вправо и влево?

Нашел нечто подобное тут , но здесь при нажатии на кнопку слайдится. 
А мне нужно переключение при слайдинге пальцем вправо и влево.

Такое возможно сделать при использовании данного способа, указанного по ссылке? 
    


Ответы

Ответ 1



Посмотрите в сторону ViewPager ViewPager туториал

Ответ 2



Как-то так public class YourActivity extends Activity {   private GestureDetector gestureDetector;      @Override   public void onCreate(Bundle savedInstanceState) {     // ...     gestureDetector = new GestureDetector(                       new SwipeGestureDetector());   }   /* ... */   @Override   public boolean onTouchEvent(MotionEvent event) {     if (gestureDetector.onTouchEvent(event)) {       return true;     }     return super.onTouchEvent(event);   }   private void onLeftSwipe() {     // Do something   }   private void onRightSwipe() {     // Do something   }   // Private class for gestures   private class SwipeGestureDetector            extends SimpleOnGestureListener {     // Swipe properties, you can change it to make the swipe      // longer or shorter and speed     private static final int SWIPE_MIN_DISTANCE = 120;     private static final int SWIPE_MAX_OFF_PATH = 200;     private static final int SWIPE_THRESHOLD_VELOCITY = 200;     @Override     public boolean onFling(MotionEvent e1, MotionEvent e2,                          float velocityX, float velocityY) {       try {         float diffAbs = Math.abs(e1.getY() - e2.getY());         float diff = e1.getX() - e2.getX();         if (diffAbs > SWIPE_MAX_OFF_PATH)           return false;                  // Left swipe         if (diff > SWIPE_MIN_DISTANCE         && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {            YourActivity.this.onLeftSwipe();         // Right swipe         } else if (-diff > SWIPE_MIN_DISTANCE         && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {           YourActivity.this.onRightSwipe();         }       } catch (Exception e) {         Log.e("YourActivity", "Error on gestures");       }       return false;     }   }

Docker ENOTFOUND при npm install?

#nodejs #npm #docker

                    
Почему при выполнении npm i я начинаю получать сообщения вида:

npm info attempt registry request try #2 at 11:45:00 PM
npm http request GET https://registry.npmjs.org/redis
npm info attempt registry request try #2 at 11:45:00 PM
npm http request GET https://registry.npmjs.org/hiredis
npm info attempt registry request try #2 at 11:45:00 PM
npm http request GET https://registry.npmjs.org/express
npm info retry will retry, error on last attempt: Error: getaddrinfo ENOTFOUND registry.npmjs.org
registry.npmjs.org:443
npm info retry will retry, error on last attempt: Error: getaddrinfo ENOTFOUND registry.npmjs.org
registry.npmjs.org:443
npm info retry will retry, error on last attempt: Error: getaddrinfo ENOTFOUND registry.npmjs.org
registry.npmjs.org:443

    


Ответы

Ответ 1



Помог перезапуск службы docker sudo service docker restart Видимо DNS нужно было обновить

Как отследить событие конца отрисовки dom?

#javascript

                    
Есть input для ввода json-schema из которой потом генерируются формочки. Схема очень
большая и при нажатии на кнопку "генерировать" происходит задержка. Причина задержки:
отрисовка dom. 
Я пытаюсь добавить loader. 
Сама функция-обработчик кнопки "генерировать" - работает быстро, и когда я пытаюсь
навесить стили, что бы показать и скрыть лоадер оно не срабатывает, т.к. оно очень
быстро выполняется и пользователь просто не замечает этого. 
Вопрос: есть ли какой-нибудь способ отследить событие конца отрисовки dom?

Это обработчик нажатия на кнопку:

 $('#loader').addClass('active-loader');

 try {
     schema = JSON.parse($schema.value);
 }
 catch (e) {
     alert('Invalid Schema: ' + e.message);
     return;
 }
 // Вызывается метод, который перерисовывает DOM из json-schema
 // json-schema большая. 1.5к строк
 reload();

 // Проблема в том, что эта строка отрабатывает быстрее чем перестроится dom      
 // Это происходит мгновенно. 
 $('#loader').removeClass('active-loader');


Проблема в том, что reload() отрабатывает быстро и loader сразу ныкается. Но dom
еще перерисовывается, хотя функции уже отработали 
    


Ответы

Ответ 1



Что, если рендерить не в DOM, а в переменную, и всё это время показывать «загружается..». А вставка уже отрендеренного html формы в родительский элемент, должно быть, гораздо быстрее, чем живой рендер по одному элементу в DOM напрямую? P.s. Сомневаюсь, что именно отрисовка занимает какое-то заметное время. Но даже если так – может, просто подобрать «на глаз» и наивно ставить setTimeout()? P.p.s. Есть события, вне стандартов, специфичные для бразуеров, которые используются в девелоперских тулзах для оценки эффективности рендеринга страниц, в основном. Но вы можете попробовать использовать их у себя. Напр. для Mozilla это событие MozAfterPaint – когда окончилась именно очередная отрисовка.

Ответ 2



Сложно дать правильный ответ, не зная что делает Ваша функция reload, но, как вариант, в эту самую функцию можно передать callback, закрывающий loader, либо же поместить логику loader'а в саму функцию reload. Если же в этой функции используется location.reload, то прочтите ответы на следующий вопрос. Надеюсь, мой ответ поможет Вам разобраться с проблемой. Удачи!