Страницы

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

вторник, 16 октября 2018 г.

Почему GitHub считает, что другой человек запушил коммит, который на самом деле запушил я?

Создал пустой GitHub репозиторий. Запушил в него свой единственный локальный коммит. Обновил страницу репозитория на GitHub'е, а там написано, что закоммитил какой-то неизвестный мне человек. Почему?

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

Интересно также, что GitHub считает, что этот репозиторий, созданный собственноручно мной 20 минут назад, создан тем самым matthewferderber'ом:

А также тот коммит, который якобы он сделал в мой репозиторий, не отображается в истории его активности


Ответ

Скорее всего неверно указан пользователь в конфигурации git. Чтобы проверить, нужно в консоли набрать git config --list
В списке проверить, что поле user.email присутствует один раз и заполнено правильно.
Как настроить конфиги верно:
Видео: на youtube Статья в книге: Первоначальная-настройка-Git

Разница между VARCHAR и VARCHAR2

Все кто имел дело с БД Oracle, знают, что объявлять символьные поля и переменные надо как VARCHAR2, а не VARCHAR
Но эти типы данных вроде синонимы:
CREATE TABLE table1 ( id number, text VARCHAR(10), text2 VARCHAR2(10) );
Name Null Type ----- ---- ------------ ID NUMBER TEXT VARCHAR2(10) TEXT2 VARCHAR2(10)
Так какая все таки между ними разница?


Ответ

На данный момент они синонимы.
VARCHAR зарезервирован Oracle для поддержки, в будущем, различия между NULL и пустой строкой, как описано в стандарте ANSI
VARCHAR2 не делает различий между NULL и пустой строкой, и никогда не будет делать.
Если вы полагаетесь на то, что пустая строка и NULL - одно и то же, используйте VARCHAR2
перевод ответа @Quassnoi

Ускорение генерации excel файла на c#

Ситуация следующая:
Необходимо из набора данных (порядка 7000 значений) сгенерировать отчет. Структура отчета задается шаблоном (набор стандартных блоков и порядок значений в строках блока, количество строк в блоке и количество заполняемых ячеек варьируется), ячейки в которые необходимо вставить данные ищутся поиском по ключевому тексту для значения. После вставки данных незаполненные ячейки очищаются (тот же поиск, но вставка пустого текста, а не значений). Вставка занимает в среднем 87с., удаление 33с. Есть варианты ускорить работу приложения?
Код примерно следующий:
foreach(значения) { rngFind = rngReport.Find(Ключевой текст, Type.Missing, Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlWhole, Excel.XlSearchOrder.xlByColumns, Excel.XlSearchDirection.xlNext, false, Type.Missing, false); if (rngFind != null) { rngFind.HorizontalAlignment = Excel.XlHAlign.xlHAlignRight; rngFind.Value2 = Значение; } }
while (flag) { rngFind = rngReport.Find(Элемент ключа, rngReport.Cells[1, 1], Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlPart, Excel.XlSearchOrder.xlByRows, Excel.XlSearchDirection.xlNext, false, Type.Missing, false); if (rngFind != null) { rngFind.HorizontalAlignment = Excel.XlHAlign.xlHAlignRight; rngFind.Value2 = ""; } }
Дополнение:
Ускорит ли работу вариант со сбором значений в массив по шаблону, а потом уже вставкой массива в excel без поиска, просто по тем же индексам что в массиве?
Дополнение2: Добавление в код следующих строк ускорило работу на 13%:
xlApp.Calculation = Excel.XlCalculation.xlCalculationManual; xlApp.ScreenUpdating = false;
Заметки: Calculation можно изменить только при открытом документе и ручной расчет влияет на доступность буфера обмена (при дефолтном значении во время генерации документа нельзя было что-то скопировать в windows).
Для ускорения работы с данными можно работать с массивом вместо Range (Object[,] vals = (System.Object[,])wsReport.Cells.get_Range(from, to)), но так не получается сохранять форматирование из шаблона, как обойтись без Range, но сохранить форматирование?
Похожее обсуждение на stackoverflow.com. Статья на microsoft.com по работе с массивом вместо range.
Дополнение 3: Удалось сравнить Interop и EPPlus (3.0.0.2) на генерации одинаковых документов: Interop медленнее в ~20 раз.


Ответ

Делай как я: Object[,] vals = (System.Object[,])wsReport.get_Range(from, to).get_Value(Type.Missing); В этом массиве набираются и изменяются итоговые данные. Excel.Range format = wsReport.Cells.get_Range(from, to); Этот range используется для вставки форматов из шаблонов. При получении блока из шаблона (rng) делаю так: rng.Copy(Type.Missing);//скопировали в буфер ((Excel.Range)format[fromRow, 1]).PasteSpecial(Microsoft.Office.Interop.Excel.XlPasteType.xlPasteFormats, Microsoft.Office.Interop.Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone, Type.Missing, Type.Missing);//скопировали форматирование из шаблона на итоговый лист
Object[,] tmpvals = (Object[,])rng.get_Value(Type.Missing);//взяли значения из шаблона, теперь надо вставить в итоговый массив данных for (int i = 1; i <= rng.Rows.Count; i++) { if (fromRow > vals.GetUpperBound(0)) break; for (int j = 1; j<= rng.Columns.Count; j++) { vals[fromRow, j] = tmpvals[i,j]; } fromRow++;//курсор на последнюю строчку } Вместо Find приходится делать так: foreach (значения) { for (int i = nRows - dx; i <= nRows; i++) { for (int j = 2; j < vals.GetUpperBound(1); j++) { if (vals[i,j]!=null && vals[i, j].ToString() == ключевой текст) { vals[i, j] = значение; goto Found; } } } Found: ; } В итоге время формирования документа со 150с. (вставка строк 0.6с, вставка значений 86с., удаление 32с.) уменьшилось до 45с (вставка строк 13с. вставка данных в массив 0.13с., удаление 0.32с, итоговая вставка 0.16).

Лицензия GNU AGPLv3 и play market

Допустим, есть опенсорсная библиотека, распространяемая под лицензией GNU AGPLv3. Я хочу использовать ее в своем приложении (исходники править не буду).
Могу ли я использовать свое приложение в коммерческих целях (выложить на маркет как free app)? Если я нарушаю лицензию, могут ли меня вычислить и покарать? Если я писал приложение под заказ, может ли заказчик выложить его на маркет?


Ответ

Удивительно читать упражнения отдельных деятелей даже без намека на ссылку на оригинал собственно самой лицензии. Радуют опусы типа: Раз либа - опенсорс, да еще и распространяется по свободной лицензии - вы ничего не нарушаете и можете свободно использовать её в своих целях. Это распространенное заблуждение. Есть варианты, напрямую запрещающие их использование в коммерческих целях, например Creative Common Non-Commercial Что касается лицензии AGPL v.3, то условия по поводу либ довольно простые: При распространении не-исходных форм необходимо: опубликовать на каждой копии уведомление об авторском праве, сохранить все уведомления об авторских правах, сохранить все уведомления об отсутствии гарантий, приложить копию данной лицензии, приложить заметное уведомление об изменении кода программы, указать дату внесения изменений, распространять на условиях данной лицензии все внесенные изменения, В конкретном случае, указанном ТС, необходимо в пункте About программы сделать сноску на копирайты авторов либы, URL с локацией либы и привести текст лицензии (да-да, сделать не ссылку, а именно приложить прямо сам текст лицензии - см. приложить копию данной лицензии). Update Прозвучал вопрос: карают ли за нарушение лицензий? Карают-карают, так покарают, что мало не покажется. У меня удалили из маркета аппу со 100 тыс. закачек только за то, что в About не привел ссылку на лицензию на использование иконки, скачанной в WikiMedia. Update2 Прозвучал еще 1 вопрос: может ли заказчик сам выложить его на маркет? Это довольно сложный вопрос. Исходя из общей логики и здравого смысла, если вы разработали аппу под заказ, то вы лишаетесь авторских прав, и авторские права на публикацию и извлечение дохода от публикации переходят к заказчику. В реальной жизни, если у вас с заказчиком отсутствует договор об отчуждении/переходе авторских от автора к заказчику, то заказчик не имеет прав на продукт. Уже были таковые прецеденты судебных дел. Чтобы защититься, заказчику необходимо заключить письменный договор с вами, ну или на худой конец акт передачи/отчуждения авторских прав. Форма договора обсуждалась на Хабре То есть если, не имея такого договора, заказчик опубликовал работу на маркете, то это прямое нарушение действующего законодательства, хотя с точки зрения здравого смысла он прав. Как поступить, решайте сами. И по совести, и по закону будет правильно составить бумажку, в которой говорится о переходе авторских прав от вас к заказчику.

Абстрактный класс-Singleton на java

Некоторое время назад писал на юнити. Использовал на шарпе такой класс:
public abstract class MySingleton { private static T _instance;
public static T Instance { get { if (_instance == null) _instance = (T)Activator.CreateInstance(typeof(T));
return _instance; } }
public static void ForgetInstance() { _instance = default(T); }
protected MySingleton() {
}
Можно ли как-то извернуться, чтобы написать похоже на java?
В лоб то, говорит: "Cannot make a static reference to the non-static type T"


Ответ

Как я понимаю, хочется хранить по одному объекту для каждого запрошенного класса, созданному с помощью конструктора по умолчанию. Для этой цели можно завести ConcurrentHashMap, Object>
import java.util.concurrent.ConcurrentHashMap;
public class MySingleton { private static ConcurrentHashMap, Object> map = new ConcurrentHashMap<>();
@SuppressWarnings("unchecked") public static T getInstance(Class clazz) { T object = (T) map.get(clazz); if(object == null) { try { object = clazz.newInstance(); } catch (IllegalAccessException | InstantiationException | SecurityException ex) { throw new RuntimeException(ex); } T oldObject = (T) map.putIfAbsent(clazz, object); if(oldObject != null) // ой, другой поток вперёд успел return oldObject; } return object; }
public static void forgetInstance(Class clazz) { map.remove(clazz); } }
Соответственно использовать как-то так:
public static void main(String[] args) { String str = MySingleton.getInstance(String.class); String str2 = MySingleton.getInstance(String.class); System.out.println(str == str2); // true MySingleton.forgetInstance(String.class); }

Автогенерация классов в C++

Имеется структура данных, подобная следующей:
Group_1 Type_1_1 Variable_1_1 . . . Type_1_N Variable_1_N Group_1_1 Name_1_1 Type_1_1_1 Variable_1_1_1 . . . Type_1_1_N1 Variable_1_1_N1 . . . Group_1_M Name_1_M Type_1_M_1 Variable_1_M_1 . . . Type_1_M_N2 Variable_1_M_N2
Важно, что число групп и число уровней вложения может быть произвольным. Внутри каждой группы могут быть как другие группы, так и переменные. В общем случае на типы переменных никакие ограничения не накладываются.
Для указанной структуры необходимо построить C++-код следующего вида:
class Group_1_1 { public : Type_1_1_1 Variable_1_1_1; // . . . Type_1_1_N1 Variable_1_1_N1; void f(Worker& worker) { worker.begin("Group_1_1"); worker.work("Variable_1_1_1", Variable_1_1_1); // . . . worker.work("Variable_1_1_N1", Variable_1_1_N1); worker.end(); } } // . . .
class Group_1 { public : Type_1_1 Variable_1_1; // . . . Type_1_N Variable_1_N; Group_1_1 Name_1_1; // . . . Group_1_M Name_1_M; void f(Worker& worker) { worker.begin("Group_1"); worker.work("Variable_1_1", Variable_1_1_1); // . . . worker.work("Variable_1_N", Variable_1_1_N1); Name_1_1.f(worker); // . . . Name_1_M.f(worker); worker.end(); } }
Здесь Worker - некоторый внешний класс.
Построить код необходимо без использования каких-либо внешних инструментов, можно использовать только стандартные возможности компилятора и препроцессора. То есть можно использовать макросы и шаблоны, но нельзя запускать какие-либо программы, не входящие в состав компилятора. Можно при этом ограничиться стандартом c++11, совместимость с предыдущими стандартами не требуется. Решение должно работать по меньшей мере со следующими компиляторами: GCC 4.9+ (Linux), MinGW 4.9+ (Windows), MSVC 2015.
Собственно вопрос: можно ли это реализовать и если можно, то как?


Ответ

Предлагаю решение с ипользованием boost::preprocessor. Пока что это решение только половины задачи, генерации отдельных классов.
Входные данные должны быть представлены примерно так:
#define GEN_GROUP 1 #define GEN_VAR 0
#define MY_STRUCT \ (GEN_GROUP, AType, A, (GEN_VAR, int, AInt) \ , (GEN_GROUP, BType, B, (GEN_VAR, int, BInt) \ , (GEN_VAR, float, BFloat) \ ) \ , (GEN_VAR, char, AChar) \ )
В понятиях boost::preprocessor это кортежи (tuple). А точнее кортежи которые содержат другие кортежи и таким образом образуют дерево. Струтура это дерева такая: элемент 0 - тип узла (группа или переменная), элемент 1 - тип данных, 2 - имя узла, и в случае группы остальные элементы начиная с 3 это поля или подгруппы:
группа = (1, тип, имя, [переменная | группа]+ ) переменная = (0, тип, имя)
Использовать эту структуру надо следующим образом, приведу просто код с коментариями:
#include
#define GEN_NODE_TYPE(node) BOOST_PP_TUPLE_ELEM(0, node) #define GEN_TYPE(node) BOOST_PP_TUPLE_ELEM(1, node) #define GEN_NAME(node) BOOST_PP_TUPLE_ELEM(2, node) #define GEN_CHILDS(node) \ // конвертируем в список, выкусываем хвост начиная с элемента 3 BOOST_PP_LIST_REST_N(3, BOOST_PP_TUPLE_TO_LIST(node))
// функтор для генерации полей класа вида "тип имя;" #define GENERATE_MEMBER_PRED(r, data, member) \ GEN_TYPE(member) GEN_NAME(member);
// функтор для генерации вызовов worker внутри фнукции f #define GENERATE_WORK_CALL_PRED(r, data, member) \ BOOST_PP_IF(GEN_NODE_TYPE(member) \ // если тип "группа" , GEN_NAME(member).f(worker) \ // то "имя.f(worker)" , worker.work(BOOST_PP_STRINGAZE(GEN_NAME(member)) \ // заковычиваем имя ,GEN_NAME(2, member)) \ // иначе worker.work("имя", имя) ); // точка с запятой для всех
#define GENERATE_CLASS(node) \ class GEN_TYPE(node) \ // "class тип" { \ public: \ \ // генерируем поля BOOST_PP_LIST_FOR_EACH( \ GENERATE_MEMBER_PRED \ // выполняем для каждого элемента , _ \ // здесь можно пусто , GEN_CHILDS(node) \ // список детей ) \ \ void f(Worker & worker) \ { \ worker.begin(BOOST_PP_STRINGAZE(GEN_TYPE(member))); \ // заковычивам тип \ \ // генерируем вызовы worker для полей BOOST_PP_LIST_FOR_EACH( \ GENERATE_WORK_CALL_PRED \ // выполняем для каждого ребенка , _ \ // здесь можно пусто , GEN_CHILDS(node) \ // список детей ) \ \ worker.end(); \ } \ };
Результат для GENERATE_CLASS(MY_STRUCT)
class AType { public: int AInt; BType B; char AChar;
void f(Worker & worker) { worker.begin("AType"); worker.work("AInt", AInt); B.f(worker); worker.work("AChar", AChar); worker.end(); } };
Как видите, классы для вложенных групп не генерируются, но это уже хоть что-то. Чтобы сделать вложенные группы необходимо реализовать обход входного дерева, при котором для каждого узла, если он группа, вызывать GENERATE_CLASS. Так как препроцессор не поддерживает рекурсию макросов, обход надо делать нерекурсивный со стеком. На boost::preprocessor по идее это возможно, но сложно, предлагаю это для самостоятельной проработки.
Внимание! Самое большое ограничение такого подхода в том, что бесконечную структуру обработать не получится. Так как количество итераций в любом циклическом операторе boost::preprocessor ограничено, равно как и в любом другом подобном инструменте основанном на препроцессоре Си. Сейчас, например, максимальное количество итераций для FOR_* составляет 256. Поэтому для больших циклов вам нужно править библиотеку boost::preprocessor либо делать свой клон с каким вам надо количеством итераций.

Определить перекрыт ли элемент другим элементом

Возможно ли определить перекрытие элемента другим элементом, при условии что не известен элемент который будет перекрывать?
var e = document.getElementById('e'); var eR = e.getBoundingClientRect(); var all = document.getElementsByTagName('*'); for (var i=0, max=all.length; i < max; i++) { var cR = all[i].getBoundingClientRect(); if(all[i] != e) { if (((cR.top <= eR.top) && (eR.top <= cR.bottom)) && ((cR.top <= eR.bottom) && (eR.bottom <= cR.bottom)) && ((cR.left <= eR.left) && (eR.left <= cR.right)) && ((cR.left <= eR.right) && (eR.right <= cR.right))) { //var inside = true; var style = window.getComputedStyle ? getComputedStyle(all[i]) : all[i].currentStyle; if(style.zIndex >= 1) { var overlap = true; console.log(style.zIndex); } } } } .wrap { width:700px; overflow:hidden; height:600px; background-color:yellow; z-index:9999; } .behind { position: absolute; left:8px; top:0px; width:468px; height:160px; background-color:rgba(255, 0, 0, 0.71); z-index: 999; } .container { background-color:black; left:20px; top:50px; width:468px; height:60px; color:#fff; }

ad

Пример на JSFiddle UPD
Вот что получилось, проблема в том, что если у родителя (.wrap) стоит z-index >0 он не перекрывает потомка (.container), а скрипт проверяет это условие и получается ложное перекрытие. Я правильно понимаю что родитель может перекрыть потомка только если у потомка отрицательный z-index?


Ответ

Как вариант, можно получить х,у координаты нашего "container" элемента и его х,у + его размер. Далее, пройтись циклом по всему DOM (по всем элементам, исключая наш "container") и проверять их координаты учитывая размеры и параметр z-index, который должен быть меньше чем у "container" в случае если есть совпадения координат. Это все можно или на Javascript сделать, или с JQuery.
Например, с JQuery: http://www.sitepoint.com/jquery-coordinates-element/
var ctrxCoord = $(".container").offset().left; var ctryCoord = $(".container").offset().top; var ctrwidthCoord = ctrxCoord + $(".container").width(); var ctrheightCoord = ctryCoord + $(".container").height();
Нужно проверить, возможно, для добавления, нужно делать с parseInt(ctryCoord) ...
Больше информации (англ.): https://stackoverflow.com/a/21274679/873481 и http://www.dyn-web.com/javascript/element-location/
Думаю, комментарий cyadvert может также быть верным.
Еще вариант - document.elementFromPoint https://stackoverflow.com/a/3942852/873481