Страницы

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

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

Фон состоящий из 2-х для input type=“range”

Интересует вопрос, есть input type="range", и нужно его стилизовать так, чтобы получился тот, что на картинке. Я пробовал ставить разные градиенты, но в этом не силен и ничего не вышло. Может кто нибудь помочь?

input[type=range] { background: -webkit-gradient(linear, left top, right top, color-stop(30%, #008000), color-stop(30%, #ffffff), color-stop(30%, #ffffff)); background: linear-gradient(left, #008000 30%, #ffffff 30%, #ff0000 30%); background-size: 1% 100px; } .game_range { width: 60%; margin-top: 40px; margin-bottom: 0px; -webkit-appearance: none; } input { outline: none; border: none; cursor: pointer; } input[type=range]::-webkit-slider-thumb { ; -webkit-appearance: none; border-radius: 50%; background: #fff; border-width: 2px; border-style: solid; border-image: linear-gradient( -175deg, rgb(116, 70, 232) 0%, rgb(15, 137, 248) 100%); border-image-slice: 5; width: 15px; height: 15px; }


Ответ

Пришлось переделать. В ::-webkit-slider-thumb вставил background вместо border-image, насколько мне известно — border-image не взаимодействует с border-radius, поэтому вставил SVG в background(изменить цвет градиента в SVG можно, меняя значение stop-color в linearGradient. Размер — width & height & viewBox атрибуты SVG, а также основные свойства ширины и высоты thumb). Белые полоски сделаны через псевдоэлемент.
for (input of document.querySelectorAll(".range")) { active(input); } document.addEventListener("input", function(e) { var input = e.target; active(input); }); function active(input) { var min = input.getAttribute("min"); var max = input.getAttribute("max"); input.style.setProperty("--val", (input.value - min)); } * { margin: 0; padding: 0; } html, body { height: 100%; } body { display: flex; justify-content: center; align-items: center; } .range { position: relative; -webkit-appearance: none; cursor: pointer; width: 50%; height: 10px; } .range::-webkit-slider-thumb { position: relative; -webkit-appearance: none; background: url('data:image/svg+xml;utf8,'); width: 15px; height: 15px; margin-top: -2px; z-index: 4; } .range::before { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(to right, white 30%, transparent 30%); background-size: 4px 100px; z-index: 3; } .range::-webkit-slider-runnable-track { height: 100%; background: linear-gradient(to right, #ff0b34 calc(var(--val)*1%), #78d151 0); } .range::-ms-fill-lower { background: #ff0b34; } .range::-ms-fill-upper { background: #78d151; }

Хранение, доступ и жизненный цикл данных необходимым для отрисовки

Имеется простая 2D игра с видом сверху и в профиль (как в Heroes of Might and Magic III). Игровая карта - тайловая, процедурно генерируемая, её размер - не ограничен. По мере перемещения персонажа подгружаются новые участки карты (чанки), другие удаляются.
Каждый объект, который должен отображаться на экране, содержит компонент GraphicsInfo, который в свою очередь хранит такие данные как позиция на экране, размеры и т.д. Идея заключается в том, чтобы в части программы, отвечающей за отрисовку, хранить коллекцию всех этих объектов удобным для отрисовки способом.
Но появилась сложность - при выгрузке чанков из памяти нужно как-то определять, какие именно объекты GraphicsInfo там находились и удалять их из коллекции.Все осложняется ещё тем, что загрузка и выгрузка чанков осуществялется в отдельном потоке. Поэтому хранить объекты в самих чанках и удалять их оттуда непосредственно при выгрузке не хотелось бы, т.к. задача сильно усложняется проблемой синхронизации разных потоков.
Вопрос: как проверить - какие объекты находились на выгруженных чанках? Хотелось бы чтобы код отвечающий за загрузку и выгрузку карты был как можно меньше связан с кодом отвечающим за отрисовку объектов.


Ответ

По идее, вы храните объекты (или ссылки на них, не суть) в чанках. Загрузили чанк - добавили его объекты к отрисовке. Выгрузили чанк - убрали его объекты из отрисовки.
Для упрощения, можете в каждом объекте добавить поле "к какому чанку он относится". Тогда удаление станет еще проще. Хотя, чанки обычно квадратные и вычислить чанк по расположению объекта проще простого.
Все операции по добавлению и удалению, естественно нужно делать в критических секциях (или других объектах синхронизации), во избежании ошибок.

оставить только последних N записей в истории каждого пользователя

Существует таблица
CREATE TABLE `user_histories` ( `id` int(10) UNSIGNED NOT NULL, `user` int(10) UNSIGNED NOT NULL, `item` int(10) NOT NULL, `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP )
INSERT INTO `user_histories` (`id`, `user`, `item`, `created_at`) VALUES (25, 1, 5807, '2018-06-16 11:52:49'), (26, 1, 8415, '2018-06-16 11:58:30'), (27, 1, 7219, '2018-06-16 12:33:50'), (28, 1, 1518, '2018-06-17 07:31:24'), (29, 1, 9089, '2018-06-17 07:41:53'), (30, 1, 3454, '2018-07-13 14:41:55'), (31, 1, 5595, '2018-07-13 15:19:36'), (32, 1, 7611, '2018-07-13 15:21:27'), (33, 2, 1518, '2018-07-20 16:19:29'), ... (10 строк) (40, 2, 7960, '2018-07-20 16:20:11'), (41, 3, 5609, '2018-07-20 16:20:15'), (42, 3, 8705, '2018-07-20 16:20:20'), (43, 3, 1737, '2018-07-20 16:22:56'), (44, 3, 7260, '2018-07-20 16:23:09');
в которой хранятся история просмотренных пользователем страниц.
Как при помощи одного запроса удалить записи (историю посещений), оставив для каждого пользователя только последних 5(по времени)?
Учитывая что mysql не поддерживает limit в подзапросах и не позволяет использовать offset в операторе DELETE


Ответ

Обходим ограничение при помощи вложенного запроса за место прямого доступа к таблице:
DELETE uh FROM user_histories uh WHERE uh.created_at < ( SELECT MIN(uh1.created_at) FROM ( SELECT * FROM user_histories ) uh1 WHERE uh1.user = uh.user AND uh1.created_at > uh.created_at HAVING COUNT(*) >= 5)
Идея взята отсюда: https://dba.stackexchange.com/questions/39484/delete-the-n-oldest-entries-grouped-by-multiple-columns

Создать идентичные 9х9 элементов TextView в виде таблички - с равными размерами

У меня есть компоновка LinearLayout вертикальной ориентации, в которой находятся 9 компоновок LinearLayout горизонтальной ориентации, в каждой из которых по 9 TextView (итого 9 * 9 = 81 элемент TextView). Для грамотной реализации этого творчества я создаю по 9 горизонтальных компоновок LinearLayout и по 9 TextView в каждой из них в Java-коде, а затем, соответственно, добавляю их в основную компоновку компонента Activity примерно так:
for (int y = 8; y >= 0; y--) { LinearLayout mLinearLayout_row = ...//компоновка горизонтальной ориентации for (x = 0; x < 9; x++) { TextView mTextView = layoutInflater.inflate(R.layout.mtextview, ... mLinearLayout_row.addView(mMTextView); } myMainActivityLayout.addView(mLinearLayout_row, 0); }
Все компоновки имеют длину MATCH_PARENT, а высоту WRAP_CONTENT. Вот код mtextview.xml

На экране ширИны всех элементов TextView выглядят равными (если не вглядываться). Но на самом деле система Android задаёт ширину нескольким последним элементам с правой стороны во всех рядах чуть меньшую ширину - это система вычисляет алгоритмом за счёт известного значения атрибута layout_weight у всех TextView
Теперь перейду к проблеме. У меня не получается сделать элементы TextView квадратными, таблица выглядит приплюснутой.

Я пробовал следующие способы:
Использовать кастомный TextView, в классе которого переопределив метод onMeasure
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, widthMeasureSpec); }
Метод очень плох, так как элементы то делаются квадратными, но слева они большие, а справа маленькие - это очень некрасиво выглядит.
Использовать кастомную основную компоновку LinearLayout, в классе которой переопределив метод onMeasure (так же, как в п.1) и установив значение атрибута layout_height у TextView на match_parent - вообще никаких изменений. В коде компонента Activity, в которой всё это происходит, переопределить метод onResume, в котором пытаться получить ширину всех TextView и задать им высоту, равную известной ширине... в общем-то способ не профессиональный и не оптимальный, по моему мнению, но, несмотря на это, я попробовал использовать этот способ, а оказалось, что, когда вызывается метод onResume система ещё не знает ширину элементов!!! (значение функции mTextView.getWidth(), полученное в этом методе равно 0).

Сожалею, что нереально тяжело въехать, в чём же у меня заключается проблема, но я постарался максимально подробно и корректно описать её :).


Ответ

Для того, чтобы сделать ячейки масшатбируемыми и квадратными, можно использовать свойство соотношения сторон app:layout_constraintDimensionRatio в ConstraintLayout


Это позволит вам сделать ячейки квадратными, вне зависимости от расширения экрана, т.к. они просто ужмутся по высоте и ширине
Но я предлагаю пойти вам дальше и переверстать экран с помощью recyclerView (как предложил Виталий в комментариях). Во-первых, это избавит вас от проблемы адресации к этим ячейкам, ведь их нужно будет заполнять и считывать. А во-вторых, реализация с RecycelerView будет эстетичнее (в разметке RecyclerView + адаптер + ViewHolder - вы сами убедитесь в простоте такой реализации). Установив размер 1 в item RecyclerView, вы автоматически его установите всем ячейкам.
Адаптер для RecyclerView стандартный, но нужно переопределить LayouManager. Создаете LayoutManager, наследуете его от GridLayoutManager (можно внутри адаптера):
private static class NonScrollableGridLayoutManager extends GridLayoutManager {
NonScrollableGridLayoutManager(Context context, int span) { super(context, span); }
@Override public boolean canScrollVertically() { return false; }
@Override public boolean canScrollHorizontally() { return false; } }
В адаптере создаете метод, возвращающий объект LayoutManager
public static RecyclerView.LayoutManager getLayoutManager(Context context) { return new NonScrollableGridLayoutManager(context, COUNT_OF_ITEM_IN_LINE); }
Затем устанавливаете для RecyclerView ваш LayoutManager
binding.monthContent.setLayoutManager(CalendarAdapter.getLayoutManager( binding.getRoot().getContext())); binding.monthContent.setAdapter(daysAdapter); binding.monthContent.setItemAnimator(null);
Не правда ли удобно?

Аргумент в сообщении

Как это реализовать?
'Тики, переверни (предложение)' => utf8_strevv("предложение")
Нужно как-нибудь взять предложение после слова "переверни" и внести его в utf8_strrev()
Код:
secret, $secretKey) !== 0 && strcmp($data->type, 'confirmation') !== 0) return;
switch ($data->type) { case 'confirmation': echo $confirmationToken; break;
case 'message_new': $user_id = $data->object->from_id; $user_info = json_decode(file_get_contents("https://api.vk.com/method/users.get?user_ids={$user_id}&access_token=$token&v=5.80")); $user_name = $user_info->response[0]->first_name; $message = $data->object->text; $url = 'https://vk.com/foaf.php?id='.$user_id; $file = file_get_contents($url); preg_match_all('##U', $file, $out, PREG_SET_ORDER); if (isset($out[0])) { $date = $out[0][1]; $dt = new DateTime($date); } $random_words = array ( 'Орёл', 'Решка' ); $random_word = $random_words[array_rand($random_words)]; function utf8_strrev($str) { preg_match_all('/./us', $str, $ar); return join('', array_reverse($ar[0])); } $messages_array = [ 'Тики, хелп' => "💎Мои команды:
(Пример: Тики, хелп)

Команды для обычных:

🌕Тики, хелп
🌕Тики, привет
🌕Тики, как дела?
🌕Тики, что делаешь?
🌕Тики, какой у меня ID?
🌕Тики, какая сегодня дата?
🌕Тики, сколько время?
🌕Тики, монетка
🌕Тики, создатель
🌕Тики, рандом
🌕Тики, дата регистрации
🌕Тики, админы", 'Тики, привет' => "🖤Привет {$user_name}!", 'Тики, как дела?' => "🖤Нормально, {$user_name}, а у тебя как?", 'Тики, что делаешь?' => "🖤С тобой переписываюсь, и мне очень весело... А ты?", 'Тики, какой у меня ID?' => "🖤Твой ID: {$user_id}, и он самый крутой!", 'Тики, какая сегодня дата?' => "🖤Дата: ".date("d.m.Y"), 'Тики, сколько время?' => "🖤Время: ".date("H:i:s"), 'Тики, монетка' => "🖤Выпадает: {$random_word}", 'Тики, создатель' => "🖤Создатель: [id406404515|Константин]", 'Тики, рандом' => "🖤Рандомное число: ".rand(1, 100), 'Тики, дата регистрации' => "🖤Дата регистрации ВКонтакте: ".$dt->format('d.m.Y')." ".$dt->format('H:i:s'), 'Тики, админы' => "🖤[id406404515|Константин]", 'Тики, переверни' => ]; foreach($messages_array as $k => $v) { if ($message == $k) { $otvet = $v; } } $request_params = array( 'message' => $otvet, 'user_id' => $user_id, 'access_token' => $token, 'v' => '5.80' );
$get_params = http_build_query($request_params);
file_get_contents('https://api.vk.com/method/messages.send?' . $get_params);
echo('ok');
break;
case 'group_join': $user_id = $data->object->user_id; $user_info = json_decode(file_get_contents("https://api.vk.com/method/users.get?user_ids={$user_id}&access_token=$token&v=5.80")); $user_name = $user_info->response[0]->first_name; $request_params1 = array( 'message' => "Привет {$user_name}! Это второй бот Тики. С этим ботом вы можете пообщаться, задавать ему вопросы, спрашивать и многое другое! Кстати, этот бот умеет переворачивать текст! Чтобы узнать команды напиши «Тики, хелп».", 'user_id' => $user_id, 'access_token' => $token, 'v' => '5.80' );
$get_params1 = http_build_query($request_params1);
file_get_contents('https://api.vk.com/method/messages.send?' . $get_params1);
echo('ok');
break; case 'group_leave': $user_id = $data->object->user_id; $user_info = json_decode(file_get_contents("https://api.vk.com/method/users.get?user_ids={$user_id}&access_token=$token&v=5.80")); $user_name = $user_info->response[0]->first_name; $request_params2 = array( 'message' => "Пока {$user_name}! Мы увидемся ещё? Я по тебе буду скучать(((", 'user_id' => $user_id, 'access_token' => $token, 'v' => '5.80' );
$get_params2 = http_build_query($request_params2);
file_get_contents('https://api.vk.com/method/messages.send?' . $get_params2);
echo('ok');
break; return false; } ?>


Ответ

Вся ваша реализация далеко не идеальна, рекомендую избавляться от хранения команда - ответ в массиве.
Но если для вас это удобно, этот вариант-велосипед должен подойти вам:
Короткий идентичный массив команд:
$messages_array = [ 'Тики, привет' => 'Привет', 'Тики, переверни' => 'Введите текст!', 'Тики, как дела?' => 'Хорошо' ];
Сообщение, которое приходит боту:
$message = 'Тики, переверни предложение';
Проход циклом по командам, если в $message есть начало команды, которая содержится в ключе массива $messages_array, то выполняются условия выполнения функции utf8_strrev
foreach ($messages_array as $k => $v) { if ($message == $k) $otvet = $v; elseif (preg_match("/$k/", $message) && preg_match("~$k\s(.*)~", $message, $match)) $otvet = (!empty($match[1])) ? utf8_strrev($match[1]) : $v; }
Далее используем $otvet по назначению для отправки пользователю.

Предотвратить click()

На сайте есть квест, в рандомное время появляется попап, и кто первый кликнет получает приз Но некоторые люди использую через консоль поиск элемента и click(), можно ли как-то это предотвратить, а учитывать только клик именно мышкой?


Ответ

Да. такое возможно. При клике мышкой в обработчик передается объект события, у которого есть поле isTrusted
isTrusted - свойство объекта Event, доступное только на чтение. Принимает значение true, если событие было инициировано действиями пользователя, и false, если событие было создано или изменено скриптом, либо с помощью dispatchEvent.
document.getElementById('click').addEventListener('click', (e) => console.log(e.isTrusted)); document.getElementById('click').click(); #click { border: 1px solid black; width: 200px; height: 200px; }

click me

Что из себя представляет массив в языке программирования Java?

Все мы знаем, что язык программирования Java является чисто объектным языком. Все сущности, с которыми нам приходится иметь дело и осуществлять какие-либо манипуляции, являются объектами (за исключением примитивов), в том числе и массивы. То бишь, если говорить совсем уж простыми словами, то любой массив является конкретным объектом в памяти. Java является сильно типизированным языком. Хоть и градация на языки со слабой и сильной типизацией данных является весьма условной, но Java, так или иначе, больше относится к языкам с сильной типизацией. Это ведёт нас к тому, что все данные имеют свой фиксированный тип (или класс, если говорить в терминах ООП). Вот здесь и вся загвоздка! Мне всегда хотелось узнать, каким образом описываются массивы, как некоторые абстрактные сущности, на физическом уровне. Я понимаю, что невозможно найти готовый класс, в котором бы была описана структура массивов, по той простой причине, что данная сущность является одной из фундаментальных (на равне с примивными типами данных) и её реализация спрятана где-то на уровне JVM или в каком-то другом месте.
Давайте рассмотрим тривиальный пример. Мы знаем, что размер любого массива является фиксированным и определяется на этапе создания самого массива. Сведения о размере массива хранятся в целочисленной переменной с одноимённым названием length. Сразу же возникает вопрос относительно этого поля. Откуда оно взялось? Где можно проследить всю эту внутреннюю логику (если можно так выразиться)? Идём далее. Создали массив в памяти, при этом сразу же указали его размер. Размер массива соответствует количеству однотипных элементов, которые могут храниться в этом массиве. И тут опять-таки вопрос. По какой логике JVM определяет количество элементов, которое нам необходимо? Точнее не совсем так. Понятное дело, что мы сами указываем размер массива, но разве количество полей для отдельно взятого типа данных не должно быть фиксированным?! Есть ли какой-нибудь код (пусть даже псевдокод), который мог бы хоть немного пролить свет на данный вопрос.


Ответ

Надеюсь мой ответ Вам поможет. Также прикрепил ссылки на источники, для подробного изучения.
В Java, массивы являются объектами и наследуются от Object Переменные в массиве упорядочены, индексация массива начинается с 0.
Когда мы создаем объект массива с помощью new, в куче выделяется под это дело память и возвращает нам ссылку. Но как так получается? Тип массива записывается как type [], где type - тип данных содержащихся элементов; скобки[] - это специальные символы, указывающие, что эта переменная содержит массив; число которое передаем в new int[5] - размер нашего массива.

Что представляет собой массив Java в памяти?
Размер массива не является частью его типа, поэтому скобки пустые int[] array; массив объектов будет содержать ссылки на эти объекты, а если он пока не инициализирован, то null (Значения по умолчанию в Java)
Подробнее про массивы можно почитать тут: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
Чтобы подробнее понять как создается массив рассмотрим эквивалентную запись:
String[] array = (String[]) Array.newInstance(String.class, 3);
эта запись равна этой:
String[] array = new String[3];
метод (Class componentType, int length) возвращает нам newArray(componentType, length), а вот уже реализация newArray() является native. И этот прекрасный и скрытый от наших глаз метод возвращает нам наш массив и дальше мы приводим к class [Ljava.lang.String с помощью (String[]) Array.newInstance(String.class, 3).
Ссылки на источники:
https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Array.html https://www.geeksforgeeks.org/arrays-in-java/
На уровне JVM, на примере int[]
Новый массив целых чисел создается во время выполнения операции newarray int Размер массива должен быть в стеке до выполнения этой операции; операция оставляет в стеке ссылку на массив. Ссылки загружаются и сохраняются с помощью операций iaload var и iastore var
Стоит сказать, что на уровне JVM в зависимости от типа будут вызваны соответствующие команды. Подробнее: https://www.artima.com/underthehood/objectsP.html
если ссылка на массив находится в верхней части стека, операция arraylength оставит длину массива поверх стека. И наверное как раз ее нам возвращает метод Array.getLength(array)
Подробнее:
https://cs.nyu.edu/courses/fall00/V22.0201-001/jvm3.html

Склонировать диск (в т.ч системный) в ISO

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


Ответ

Образ ISO - это простая посекторная копия диска (точнее, раздела, или "дорожки", применительно к CD), без сжатия и каких-либо служебных заголовков. Название произошло от файловой системы ISO-9660, которая была одной из первых файловых систем для CD, но фактически образ ISO может содержать любую файловую систему в зависимости от типа носителя: UDF для DVD, FAT для дискет, FAT32/NTFS для флешек и т.п. Чтобы создать такой образ, достаточно открыть диск на чтение и переписать все содержимое в файл, поэтому потребуется лишь несколько функций для работы с файлами из WinAPI. Да, конечно, это можно сделать в .NET.
Создать образ CD-ROM или другого подобного незаписываемого носителя довольно просто:
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices;
namespace ConsoleApplication1 { class Program { [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool GetDiskFreeSpace(string lpRootPathName, out uint lpSectorsPerCluster, out uint lpBytesPerSector, out uint lpNumberOfFreeClusters, out uint lpTotalNumberOfClusters);
const uint GENERIC_READ = 0x80000000; const uint FILE_SHARE_READ = 0x00000001; const uint FILE_SHARE_WRITE = 0x00000002; const uint OPEN_EXISTING = 3; const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern IntPtr CreateFile( [MarshalAs(UnmanagedType.LPTStr)] string filename, [MarshalAs(UnmanagedType.U4)] uint access, [MarshalAs(UnmanagedType.U4)] uint share, IntPtr securityAttributes, [MarshalAs(UnmanagedType.U4)] uint creationDisposition, [MarshalAs(UnmanagedType.U4)] uint flagsAndAttributes, IntPtr templateFile);
[DllImport("kernel32.dll", SetLastError = true)] static extern bool ReadFile(IntPtr hFile, [Out] byte[] lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool CloseHandle(IntPtr hObject);
static void CreateISO(string letter, string outfile) { byte[] buf; uint dwRead = 0; ulong count = 0; uint dwSectorsPerCluster, dwBytesPerSector, dwNumberOfFreeClusters, dwTotalNumberOfClusters; uint blocksize; ulong totalsize;
const uint SECTOR_SIZE = 2048; //размер сектора для CD string fmt = "\\\\.\\{0}:"; //формат имени файла для открытия тома
//найдем размер сектора и объем данных на диске bool res = GetDiskFreeSpace(letter + ":\\", out dwSectorsPerCluster, out dwBytesPerSector, out dwNumberOfFreeClusters, out dwTotalNumberOfClusters);
//вычислим размер блока, кратный размеру сектора, и общий объем данных в байтах if (res) { blocksize = dwBytesPerSector * 20; totalsize = dwSectorsPerCluster * dwBytesPerSector * (ulong)dwTotalNumberOfClusters; } else { Console.WriteLine("GetDiskFreeSpace error {0}", Marshal.GetLastWin32Error()); blocksize = SECTOR_SIZE * 20; totalsize = 4700307456; //DVD } buf = new byte[blocksize];
string volume = String.Format(fmt, letter);
//открываем том для прямого доступа на чтение var handle = CreateFile(volume, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
if (handle.ToInt64() == -1) throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
//открываем файл для записи var target = new System.IO.FileStream(outfile, System.IO.FileMode.Create);
try { while (true) { dwRead = 0; Array.Clear(buf, 0, buf.Length);
//считаем блок данных res = ReadFile(handle, buf, blocksize, out dwRead, IntPtr.Zero); if (res == false) { Console.WriteLine(); Console.WriteLine("ReadFile error {0}", Marshal.GetLastWin32Error()); break; }
if (dwRead == 0) break; //конец считывания
count += dwRead;
Console.Write(" Creating image: {0}% [{1} KB / {2} KB]
", (count * 100.0f / totalsize).ToString("F1").PadLeft(5), (count / 1024.0f).ToString("F2").PadLeft(10), (totalsize / 1024.0f).ToString("F2").PadLeft(10));
//запишем блок в файл target.Write(buf, 0, (int)dwRead); }
} finally { CloseHandle(handle); target.Close(); }
Console.WriteLine(); }
static void Main(string[] args) { CreateISO("E", "c:\\distr\\image.iso"); Console.ReadKey(); } } }
Для создания образа записываемого носителя (флешки и т.п.), необходимо сначала попросить пользователя закрыть все программы, которые его используют, и открывать диск монопольно (0 вместо FILE_SHARE_READ | FILE_SHARE_WRITE). Если этого не сделать, во время создания образа часть информации на диске может быть параллельно изменена другой программой, и образ получится в итоге в некорректном состоянии. Альтернативное решение этой проблемы - использование Volume Shadow-Copy Services (VSS).
Что касается жестких дисков, то создавать ISO-образ таким методом для них не выглядит хорошей идеей. Во-первых, открыть жесткий диск эксклюзивно не всегда получится (а системный и вовсе никогда). Во-вторых, формат ISO для них просто не предназначен, и многие утилиты вообще не смогут обработать ISO-образ для жесткого диска. Вместо этого лучше использовать специальный формат для образов жестких дисков, например VHD. Он поддерживается как средствами Windows, так и сторонними продуктами типа Акрониса. Опять же, для программного создания таких образов можно не изобретать что-то свое, а воспользоваться стандартной утилитой командной строки wbadmin, которая автоматически умеет использовать VSS и создавать образ в том числе системного диска.

Как получить ассемблерный листинг кода, созданного gcc?

Как получить ассемблерный листинг кода, созданного gcc?


Ответ

Для этого есть опция -S. $ cat z.c
int main() { return 0; }
$ gcc -S z.c && cat z.s
.file "z.c" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp movl $0, %eax popl %ebp ret .size main, .-main .ident "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5" .section .note.GNU-stack,"",@progbits

Не ставится Python на Windows XP

Друзья, помогите, пожалуйста, справится со следующей ситуацией: устанавливаю любой питон(например python-2.6.6.msi), скачанный с офф сайта питона, и при установке получаю следующее исключение.

Гугл по этому поводу молчит. Может что-нибудь посоветуете. Заранее спасибо!


Ответ

Попробуйте переустановить windows installer на какую-нибудь свежую версию, а если включено автообновление винды, то лучше всего переустановить систему и отключить обновление (практически всегда появляются глюки в системе после обновлений)... у самого стоит ХР сп2, питон 2.6.6, MSVS 2008 - проблем не возникало...

Редактирование .class файлов

Есть JAR файл. Необходимо декомпилировать один из его классов, отредактировать одно значение и закомпилировать обратно.


Ответ

Если хотите сделать это одноразово, то попробуйте JAD. Но учтите, что декомпиляторы не всегда могут получить исходник из .class-файла. Предположим, вы сумели его декомпилировать верно. После этого, его надо собрать обратно. Чтобы это сделать, надо воспользоваться компилятором.
javac -cp исходный.jar:библиотеки.jar исправленный.класс.java
(если под виндой, то библиотеки надо разделять точкой с запятой вместо двоеточия)
Ну а потом запаковать с помощью утилиты jar или какого-нибудь winrar
Если JAD не выдаёт плохой исходник, то можно попробовать другие варианты декомпиляторов. В худшем случае, вам придётся после декомпиляции разбираться в байткоде и руками править неверно декомпилированный код.
UPD
Также есть возможность вскрыть .class-файл и править его с помощью Apache BCEL. С его помощь можно подгрузить класс, модифицировать его, а потом обратно записать. Правда Apache BCEL - программное средство, а не тула, так что вам придётся написать программу, которая бы патчила класс нужным образом.

Ищу библиотеку, троичная логика

Привет всем. Не попадалась ли кому случайно библиотечка/класс хотя бы с основными тернарными операциями? Могу реализовать сам, сперва хотелось убедиться, что это не есть велосипед. Не нагуглил (мог плохо гуглить). Цель - просто интерес, практика, возможно какое-то использование в проектах, хотя пока трудновато представить. Что-то подсказывает, что можно отказаться от исключений. Кто не в курсе - это логика не 1/0, а 1/0/-1. Пару лет назад такое писал, но проект отправился в рай для жестких дисков. Код получался примерно такой: // true3=1="да", false3=-1="нет", null3=0="не знаю" $systemStatus = and3($s1->getstatus(), $s2->getstatus(), $s3->getstatus()); if ($systemStatus === true3) { echo 'all systems: ready'; } elseif ($systemStatus === false3) { echo 'all systems: idle'; } else echo 'malfunction'; PS: Ничего общего с тернарным оператором.


Ответ

Взялся сам :)
Ссылка на тестер (там же можно скачать класс и посмотреть таблицы истинности), листинг основных операторов для будущих поколений:
define('TRUE3', 1); define('NULL3', 0); define('FALSE3', -1);
function l3validate(&$arg) { if ($arg !== FALSE3 and $arg !== NULL3 and $arg !== TRUE3) { $arg = NULL3; return FALSE3; } return TRUE3; }
function l3not($a) { // НЕ, инверсия l3validate($a); if ($a === TRUE3) return FALSE3; if ($a === FALSE3) return TRUE3; return NULL3; } function l3and($a, $b) { // И, конъюнкция l3validate($a); l3validate($b); if ($a === TRUE3 and $b === TRUE3) return TRUE3; if ($a === FALSE3 or $b === FALSE3) return FALSE3; return NULL3; } function l3andm() { // И, несколько аргументов $result = TRUE3; foreach (func_get_args() as $arg) { l3validate($arg); if ($arg === NULL3) $result = NULL3; if ($arg === FALSE3) return FALSE3; } return $result; } function l3or($a, $b) { // ИЛИ, дизъюнкция l3validate($a); l3validate($b); if ($a === $b and $a === FALSE3) return FALSE3; if ($a === TRUE3 or $b === TRUE3) return TRUE3; return NULL3; } function l3orm() { // ИЛИ, несколько аргументов $result = FALSE3; foreach (func_get_args() as $arg) { l3validate($arg); if ($arg === NULL3) $result = NULL3; if ($arg === TRUE3) return TRUE3; } return $result; } function l3xor($a, $b) { // ЛИБО ... ЛИБО ..., строгая дизъюнкция l3validate($a); l3validate($b); if ($a === $b and $a !== NULL3) return FALSE3; if (($a === TRUE3 and $b === FALSE3) or ($a === FALSE3 and $b === TRUE3)) return TRUE3; return NULL3; } function l3imp($a, $b) { // ->, импликация l3validate($a); l3validate($b); if ($a === FALSE3 or $b === TRUE3) return TRUE3; if ($a === TRUE3 and $b === FALSE3) return FALSE3; return NULL3; } function l3bimp($a, $b) { // <-, обратная импликация l3validate($a); l3validate($b); if ($a === TRUE3 or $b === FALSE3) return TRUE3; if ($a === FALSE3 and $b === TRUE3) return FALSE3; return NULL3; } function l3eq($a, $b) { // =, эквивалентность l3validate($a); l3validate($b); if ($a === NULL3 or $b === NULL3) return NULL3; if ($a === $b) return TRUE3; return FALSE3; }
ЗЫ: Специально для @Dex: обсуждение терминов, таки ваша взяла) Но все же посмотрите обсуждение, оно оказалось сложным и чисто эстетическим. Даже вариант "трехвалентная" был бы верным лексически %)
UPDATE: Исправил "идейно", любое "неопознанное" превращается в NULL3. Если хочется быть более толерантным, в классе есть метод cast, округляющий до ближайшего из логических.

Защита памяти при сегментной организации

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


Ответ

По поводу дискуссии, развернувшейся в комментариях (о случайном расположении стека в памяти), можно почитать про Address Space Layout Randomization. По поводу возможности или невозможности исполнения памяти мне было интересно почитать о PaX. Случайно наткнулся на статью Касперски Переполнение буфера на системах с неисполняемым стеком, теперь знаю много умных слов :)

Тренировочные задачи по JavaScript

Где взять интересные, а главное не тривиальные задачки по JavaScript?


Ответ

Вот посмотри Quizful - тесты онлайн Тут тесты. Для тренировки вообще норм. Проверить себя да и попрактиковаться.

Верстка через javascript

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


Ответ

Не только я об этом думал http://habrahabr.ru/post/167525/

Как растянуть картинку на весь экран?

Как растянуть картинку на весь экран, если я прописываю вот этот HTML код Словарь терминов ****

Словарь терминов

У меня экран 1280x800.


Ответ

CSS3:
body { background: url(img/image.jpg) no-repeat center center fixed; background-size: cover; }
Ещё варианты

Запись телефонного разговора в Android

Доброго времени суток, Хэшкод! Возникла необходимость в собственном простом диктофоне, умеющем писать телефонный разговор. Делаю так: MediaRecorder mRecorder = new MediaRecorder(); Recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL); // если заменить VOICE_CALL на MIC то звук без проблем пишется с микрофона, прим. К.О. :) mRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR); mRecorder.setOutputFile(mFileName); mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); try { mRecorder.prepare(); } catch (IOException e) { } mRecorder.start(); В итоге получается файл весом 6 байт, который явно не содержит запись разговора. На аналогичном Хэшкоду сайте одни рекомендуют использовать приведенный выше код, другие уверяют что запись телефонного разговора невозможна в Android в принципе. Прошу помощи с приведенным выше кодом и/или также подтверждения/опровержения того, что запись беседы невозможна. Спасибо за внимание


Ответ

Со всей ответственностью заявляю, что без хака это невозможно. Об этом говорит feature request, который висит в Google уже давно безо всякой надежды на его реализацию. Фтыкать сюда С другой стороны на рынке есть некоторые приложения, которые позволяют это делать, но опять же с большими ограничениями. Все реализации написаны на основе хака радиомодулей некоторых известных кристаллов. Update Запись собственного голоса возможна - доступ к микрофону есть, а вот голос собеседника закрыт.

Есть ли в Java раннее связывание?

Модификатор final в Java не обеспечивает раннее связывание метода (на этапе компиляции), лишь не дает определить метод в наследнике с такой же сигнатурой и в том числе переопределить соответствующий метод предка, так ли это? Вопрос: Есть ли в Java ранее связывание, то есть когда уже на этапе компиляции вызову метода ставится в соответствие код который будет выполняться?


Ответ

Цитата из источника: Полиморфизм в Java
Если перегруженные методы с одинаковыми именами находятся в одном классе, списки параметров должны отличаться. Но если метод подкласса совпадает с методом суперкласса (порождающего класса), то метод подкласса переопределяет метод суперкласса. Совпадать при этом должны и имена методов и типы входных и выходных параметров. В данном случае переопределение методов является основой концепции динамического связывания (или позднее связывание), реализующей полиморфизм. Суть динамической диспетчеризации методов состоит в том, что решение на вызов переопределенного метода принимается во время выполнения, а не во время компиляции. Однако final-методы не являются переопределяемыми, их вызов может быть организован во время компиляции и называется ранним связыванием

Треугольники Python


Нужно чтобы вначале рисовался треугольник, внутри него еще 3, внутри трех еще 3 и так далее.
Как это реализуется?


Ответ

Вот вам псевдокод: SierpinskiSieve(v1, v2, v3, recdepth) : if (recdepth == 0) : draw triangle (v1, v2, v3) return
m1 = (v2 + v3)/2 m2 = (v3 + v1)/2 m3 = (v1 + v2)/2 SierpinskiSieve(v1, m3, m2, recdepth - 1) SierpinskiSieve(m3, v2, m1, recdepth - 1) SierpinskiSieve(v2, m1, v3, recdepth - 1)

Распознавание лиц на изображениях — как это работает?

Хочется быстро и относительно поверхностно въехать в тему распознавания графических образов: как даже простенькие фотоаппараты-мыльницы распознают лица/улыбки? Что прочесть? — жажду ответов тех, кто написал в итоге своё распознавание чего-то.


Ответ

Есть классические алгоритмы. Все их и используют в той или иной форме. Начните читать с Википедии, а потом пару ссылок с хабра

Использование c++ в микроконтроллерах

Подскажите пожалуйста, можно ли использовать C++ для программирования микроконтроллеров? Есть ли при этом какие либо ограничения для языка C++?


Ответ

использовать часто можно, но нужно смотреть на конкретную реализацию. К примеру, может не быть исключений. С другой стороны, с++ приносит определенный оверхед, а на микроконтроллерах часто бывает важный каждый байт, это не java c большими серверами, где можно докупить планку-другую. Но микроконтроллеры не стоят на месте и развиваются, как собственно и компиляторы. Возможно, для Вашего контроллера и Вашего случае С++ - лучший вариант.

Конструктор в контроллерах Rails

Всем доброго дня! Наверняка, вы знакомы с такой классной вещью в Rails как Layouts. Если приложение должно иметь единый интерфейс, то вполне достаточно одного такого Layoutа -application.html`, который, собственно, по умолчанию и используется, если нет ничего другого, и конфигурация осталась неизменной. Но вот если в контроллерах использовать привычный Ruby-конструктор: def initialize ... end то лэйаут не используется. Собственно, почему так? Спасибо)


Ответ

Сорри, отвык уже от Ruby. Я имею в виду следующее: class Parent def initialize puts "Parent" end end
class Child < Parent def initialize super end end
puts Child.new Я предполагаю что в Rails как его там ActionController в своём initialize как раз устанавливает layout и поэтому предлагаю вам это проверить: просто напишите def initialize super
# А здесь код, который вы хотите исполнить в своём конкретном контроллере end

Паттерны проектирования в Perl

Значит читаю вакансию perl программиста, написано : высшее образование (не программист, но технарь, инженер - проектировщик), знание Perl (имеется), ООП в perl (имеется), знание mojolicious (тоже), html; xhtml; css; javascript, паттерны проектирования - bullshit, а это зачем? Конечно есть книга банды четырех, но там все примеры для java (который не люблю, а сам синтаксис изучал для понимания примеров), т.е в теории есть понимание, но осуществить средствами языка не получается, или выходит достаточно криво с нагромождением велосипедов. Объясните, есть ли паттерны для perl?


Ответ

Есть, как и для любого языка программирования. Знание паттернов позволяет вам более грамотно и быстро писать нужный код.
Perl Design Patterns

C++11: Expression Templates VS RValue References

Доброго времени суток! В процессе размышлений над новыми возможностями привнесенными в стандарт языка С++, в частности rvalue-ссылками у меня возник вот какой вопрос. Насколько я понял, rvalue-ссылки позволяют оптимизировать возвращаемое значение, т.е. вместо копирования памяти происходит перемещение объекта в памяти (из одной области в другую). До нового стандарта, насколько мне известно, данная проблема решалась через expression templates, означает ли что применяя rvalue-ссылки можно забыть об expression templates? Или я что-то неверно понимаю? UPDATE: Уточню вопрос. Предположим у нас есть класс вида: namespace math { template class vector { public: vector() : mptr(0), msize(0) { } vector(size_t n) : msize(n) { mptr = new T[n]; } vector(const vector& other) : msize(other.msize) { if (mptr) delete[] m_ptr; if (msize == 0) { mptr = 0; } else { mptr = new T[msize]; std::copy(other.mptr, other.mptr + msize, m_ptr); } } ~vector() { if (mptr) delete[] mptr; }
vector& operator=(const vector& other) { msize = other.msize; if (mptr) delete[] m_ptr; if (msize == 0) { mptr = 0; } else { mptr = new T[msize]; std::copy(other.mptr, other.mptr + msize, m_ptr); } } vector& operator+=(const vector& x) { assert(x.size() == msize) std::transform(x.m_ptr, x.mptr+msize, mptr, std::plus()); } vector& operator-=(const vector& x) { assert(x.size() == msize) std::transform(x.m_ptr, x.mptr+msize, mptr, std::plus()); } // ... и так далее private: T* mptr; size_t msize; }; } // end namespace math Теперь предположим мы хотим перегрузить бинарные операторы (+,-, и т.д.) : template vector operator+ (const vector& x, const vector& y) { vector res(x); // временная переменная - копия x res += y; // складываем x+y return res; // возвращаем результат } Теперь мы воспользуемся нашим классом: math::vector a(1 << 18); math::vector b(1 << 18); math::vector c(1 << 18); math::vector d(1 << 18);
math::vector r = a * b - c + d; При выполнении этого кода будет создано как минимум 3 временных массива размера 2^18, в каждом операторе, которых можно избежать. Собственно это будет приводить к снижению производительности. Раньше это обходилось с помощью expression templates, которые разворачивали выражение a * b - c + d в один цикл следующим образом: math::vector r(n); for (size_t i = 0; i < n; i++) r[i] = a[i]* b[i] - c[i] + d[i]; В новом С++11 мы добавим к нашему классу конструктор перемещения и оператор перемещения (если я их правильно назвал), и объявление нашего класса поменяется следующим образом: namespace math { template class vector { public: vector(); vector(size_t n); vector(const vector&); // Перемещающий кострктор vector(const vector&& other); vector& operator=(const vector&); // Перемещающий оператор присваивания vector& operator=(const vector&&); // ... }; } Значит ли это, что теперь мы избавлены от копий и можем забыть про expression templates? Не об этом ли речь в http://www.artima.com/cppsource/rvalue.html в разделе 'Eliminating spurious copies'? P.S. Код писал без проверки - только чтобы показать идеи, так что за ошибки не пинайте :) Заранее спасибо за ответы!


Ответ

Хм. Насколько я понимаю, смысл rvalue-ссылок в том, что перемещения данных не происходит. То есть, данные, которыми пользовался объект, можно «присвоить» себе без копирования, т. к. объект всё равно собирается исчезнуть. Статья по теме rvalue references: http://www.artima.com/cppsource/rvalue.html (Бьярн среди авторов). Обновление: Я не встречался с expression template'ами раньше. Если они и правда делают то, о чём вы говорите, то rvalue references слабее, и не являются адекватной заменой. Смотрите. Если у вас есть код math::vector r = a * b - c * d + e; (я специально сделал умножение из сложения) и нужные move-конструкторы, что произойдёт? Этот код будет проинтерпретирован как math::vector&& tmp1 = a * b; math::vector&& tmp2 = c * d; math::vector&& tmp3 = tmp1 - tmp2; math::vector r = tmp3 + e; Будет вызван дважды operator * (const math::vector& l, const math::vector& r), который обязан выделять новую память, т. к. не может отобрать её у операндов. Затем будет вызван operator - (const math::vector& l, const math::vector& r), который так же не сможет отобрать память у операндов. Далее, будет вызван operator + (const math::vector& l, const math::vector& r) с той же проблемой. Финальное присваивание обычно убирается оптимизатором (RVO). Move-конструкторы вовсе не вступают в игру, за исключением может быть того, что они подменяют RVO. Что могла бы здесь улучшить move-семантика? С умножениями ничего улучшить нельзя: им по факту неоткуда брать память, придётся выделять новую всё равно. С вычитанием немного лучше: если вы определите перегрузку operator -, принимающую rvalue ref как первый аргумент, то вы сможете отобрать у него память. Для симметрии вам нужно будет сделать ещё одну перегрузку, принимающую rvalue ref как второй аргумент. И судя по всему ещё одну с двумя rvalue ref-аргументами, иначе компилятор не сможет выбрать между предыдущими двумя, если оба аргумента — rvalue ref. То же касается и сложения. Обратите внимание, что вам нужен достаточно серьёзный дубляж кода: все операторы должны быть объявлены по 3, а то и 4 раза. Таким образом, мы имеем два выделения памяти и два отбора памяти у rvalue-объектов. Это лучше, чем без move-семантики, но expression templates, как вы их описали, ещё лучше: там лишнее выделение памяти вовсе не требуется. Вывод: нет, rvalue reference'ы всё ещё не панацея.

Диагностика GUI RichTextBox

Приложение наглухо зависает при входе через RDesktop (стандартный удаленный рабочий стол Windows) на удаленный Windows Server 2008 (вышел, зашел - ого, зависло). Проблема сводится к такому простейшему коду:
ThreadPool.QueueUserWorkItem(new WaitCallback((obj) => { var richTextBox = new RichTextBox();
while (true) { richTextBox.AppendText("a");//источник зла }
}), SynchronizationContext.Current);
richTextBox изначально в дочернем потоке, поэтому InvokeRequired=false, конфликта с GUI не должно быть. Вопрос-в чем может быть проблема, с чего начать диагностику?
Update
еще такой взгляд на проблему:
ThreadPool.QueueUserWorkItem(new WaitCallback((obj) => { var richTextBox = new RichTextBox();
//Thread.Sleep(10000);//вышел-зашел в RDesktop -все нормально richTextBox.AppendText("a");//источник зла Thread.Sleep(10000);//вышел-зашел в RDesktop- приложение виснет
}), SynchronizationContext.Current);
Update 2
Такая же ошибка возникает при экранной заставке (splash screen)
Еще по теме:
Debugging Windows Forms Application Hangs During SystemEvents.UserPreferenceChanged Mysterious Hang or The Great Deception of InvokeRequired Memory Leak in ToolStripTextBoxControl What is UserPreferenceChangedEventHandler in C# winform applications? .NET 4.0 and the dreaded OnUserPreferenceChanged Hang
Изначальная задача
Требуется в отдельном (не основном) потоке сформировать большой RTF. RTF необходим, так как требуется форматирование шрифта (разные размеры шрифта и проч.) Затем сохранить в файл richTextBox.Save(файл.rtf)


Ответ

Лучше сделать поток не в очереди, а напрямую Thread.Start. Добавьте обязательно Application.DoEvent в теле потока. Поток сделать STA

Как создать библиотеку импорта для существующей DLL

Есть несколько DLL, требуется использовать функции из них в проекте на Си++. Доступа ни к исходникам ни к разработчикам у меня нет. То есть в наличии просто набор DLL как вешь в себе и документ с описанием интерфейса к ним.
Сейчас я получаю адреса функций вручную c помощью LoadLibrary и GetProcAdrress, но под мою задачу было бы удобнее иметь библиотеки импорта для них. Чтобы никаких телодвижений по инициализации не делать, не следить за ними и так далее. Так вот, как библиотеки импорта создать и вообще как они работают?


Ответ

В принципе, это неподдерживаемый сценарий: например, функции могут быть декорированы нестандартным образом, или иметь нетрадиционное соглашение о вызове.
Но тем не менее, если вы знаете точную сигнатуру функций, то можно попытаться сделать, как описано здесь
Идея №1: создать DEF-файл вручную. Это подойдёт, если функции, которые вы импортируете, есть C-функции, и вы знаете их calling convention (например, __cdecl или PASCAL (__stdcall)).
Для начала, установим, что это за функции. Для этого можно воспользоваться стандартной утилитой dumpbin с ключом /exports (не забывайте, что её нужно запускать из-под Visual Studio command prompt) или очень полезной при нативной разработке под Windows-платформу утилитой depends.exe
Для dumpbin вы получите примерно такой вывод:
...> dumpbin /exports "C:\Program Files\Far\Plugins\arclite\arclite.dll" Microsoft (R) COFF/PE Dumper Version 11.00.61030.0 Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file C:\Program Files\Far3\Plugins\arclite\arclite.dll
File Type: DLL
Section contains the following exports for arclite.dll
00000000 characteristics 54BA6E68 time date stamp Sat Jan 17 15:15:04 2015 0.00 version 1 ordinal base 19 number of functions 19 number of names
ordinal hint RVA name
2 0 00016170 AnalyseW 3 1 00016920 CloseAnalyseW 4 2 000175F0 ClosePanelW 5 3 000182A0 ConfigureW 6 4 00017DA0 DeleteFilesW 1 5 000185E0 ExitFARW 7 6 00017B00 FreeFindDataW 8 7 00017B60 GetFilesW 9 8 000179F0 GetFindDataW 10 9 00015F20 GetGlobalInfoW 11 A 000177C0 GetOpenPanelInfoW 12 B 00016030 GetPluginInfoW 13 C 00017EC0 MakeDirectoryW 14 D 00016970 OpenW 15 E 00017FD0 ProcessHostFileW 16 F 00018180 ProcessPanelInputW 17 10 00017C80 PutFilesW 18 11 000178A0 SetDirectoryW 19 12 00015FB0 SetStartupInfoW
Summary
5000 .data 16000 .rdata 9000 .reloc 1000 .rsrc 87000 .text
Отсюда вы берёте имена функций: AnalyseW, CloseAnalyseW и т. д., и превращаете их в .def-файл:
EXPORTS ; EntryName [=InternalName] [@Ordinal] [NONAME] [CONSTANT] AnalyseW CloseAnalyseW
Так работает для функций с calling convention __cdecl (она обычно принята по умолчанию). Для других вы должны задекорировать имя функции самостоятельно, согласно таблице
| Calling convention | extern "C" or .c file | .cpp, .cxx or /TP | ------------------------------------------------------------------------------------- | C convention (__cdecl) | _test | ?test@@ZAXXZ | | Fastcall convention (__fastcall) | @test@0 | ?test@@YIXXZ | | Standard call convention (__stdcall) | _test@0 | ?test@@YGXXZ | | Vector call convention (__vectorcall) | test@@0 | ?test@@YQXXZ |
— и прописать их как алиасы
EXPORTS ; EntryName [=InternalName] [@Ordinal] [NONAME] [CONSTANT] CdeclFunction PascalFunction=_PascalFunction@8
(число после @ означает количество байт в стеке, отводимое под параметры).
Теперь можно использовать команду lib /def:yourfile.def из командной строки Visual Studio, чтобы построить .exp и .lib для линковки.

Идея №2 — это создать фейк-библиотеку с такими же сигнатурами функций, построить её, и использовать её .exp и .lib вместо отсутствующих. Для этого вам придётся построить С- (или хуже того, C++-) сигнатуры нужных функций. Для сишных функций (ну или тех, которые были определены как extern "C" в исходнике) это просто: вы смотрите на декорированное имя (например, в том же depends.exe или dumpbin), определяете по таблице сверху их calling convention, и кладёте такую функцию в исходник. Не забудьте указать __declspec(dllexport) для всех, и добавочно extern "C" для сишных функций. Реализуйте функции как угодно, чтобы компилятор скомпилировал это.
Если у вас декорированные C++-сигнатуры (они выглядят как-то так: ?test@@YGXXZ) их можно превратить в правильные C++-декларации при помощи утилиты undname
...> undname ?test@@YGXXZ Microsoft (R) C++ Name Undecorator Copyright (C) Microsoft Corporation. All rights reserved.
Undecoration of :- "?test@@YGXXZ" is :- "void __stdcall test(void)"
Если у вас есть header, идущий с библиотекой, то ничего угадывать (с риском ошибиться и получить креш) не надо, просто возьмите прототипы функций оттуда (только не забудьте поменять __declspec(dllimport) на __declspec(dllexport)).
Скомпилируйте полученный файл в .obj при помощи команды
cl /c /Ob0 dllname.cpp
Ключ /c нужен, чтобы компилятор произвёл .obj, а /Ob0 — чтобы не занилайнил случайно какие-нибудь функции, которые ему покажутся ненужными (это может быть нужно в случае экспорта классов, и в любом случае не повредит).
Имея .obj, вы можете получить .lib и .def при помощи команды
lib /def: dllname.obj

Передача информации из фрагмента в фрагмент, которые находятся во ViewPager

Как можно реализовать передачу информации из одного фрагмента в другой, когда оба эти фрагмента находятся в ViewPager?
Есть класс MainActivity, в котором я реализую ViewPager со своим собственным FragmentPagerAdapter и также TabLayout, который отображает эти фрагменты как "табы".
Код инициализации ViewPager и TabLayout в MainActivity
private void initTabs() { viewPager = (ViewPager) findViewById(R.id.viewPager); TabsPagerFragmentAdapter adapter = new TabsPagerFragmentAdapter(getSupportFragmentManager()); viewPager.setAdapter(adapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabLayout); tabLayout.setupWithViewPager(viewPager); }
Код моего FragmentPagerAdapter:
public class TabsPagerFragmentAdapter extends FragmentPagerAdapter {
private String[] tabs;
public TabsPagerFragmentAdapter(FragmentManager fm) { super(fm); tabs = new String[]{ "Описание", "Карта", };
}
@Override public CharSequence getPageTitle(int position) { return tabs[position]; }
@Override public Fragment getItem(int position) { switch (position) { case 0: return Fragment_ListFragment.getInstance(); case 1: return Fragment_MapTab.getInstance(); } return null; }
@Override public int getCount() { return tabs.length; } }
Так вот, моя задача заключается в том, что мне нужно например получить некое число в первом фрагменте и передать его во второй фрагмент, который содержится в этом же ViewPager. Потом второй фрагмент должен принять это число и на основании его "перестроить" свой вид (я так понимаю это число нужно будет принимать в onCreateView методе и все "перестройку" вида проводить в нем же). После того как второй фрагмент "перестроил" свой вид, нужно чтобы ViewPager открывал автоматически второй фрагмент(как я понял нужно использовать метод setCurrentItem())
Собственно вопросы:
1.Как реализовать передачу данных и из одного фрагмента в другой?
2.И если я получу эти данные, то логику "перестройки" нужно описать в методе onCreateView?
Коды фрагментов:
Первый фрагмент(из которого я должен получить информацию, в данном случае - это позиция элемента в списке):
public class Fragment_ListFragment extends ListFragment {
private ViewPager vp;
public static Fragment_ListFragment getInstance() { Bundle args = new Bundle(); Fragment_ListFragment fragment = new Fragment_ListFragment(); fragment.setArguments(args); return fragment; }
@Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); vp = (ViewPager) getActivity().findViewById(R.id.viewPager); ArrayAdapter adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, Constants.names); setListAdapter(adapter); }
@Override public void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); long a = id; Toast.makeText(getActivity(), a + "", Toast.LENGTH_SHORT).show(); vp.setCurrentItem(Constants.TAB_MAP); } }
Второй фрагмент(в нем я должен принять эту позицию):
public class Fragment_MapTab extends Fragment { public static final int LAYOUT = R.layout.fragment_map_tab; private View view;
public static Fragment_MapTab getInstance() { Bundle args = new Bundle(); Fragment_MapTab fragment = new Fragment_MapTab(); fragment.setArguments(args); return fragment; }
@Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view = inflater.inflate(LAYOUT, container, false); return view; }


Ответ

Вопрос можно закрыть. Можно использовать такой подход:
В MainActivity нужно создать String переменную (Пусть будет TabFragment), и две функции для изменения и извлечения оной (String getTabFragment и void setTabFreagment). Во фрагменте которому нужно что-то передать создаем строку и присваиваем ей результат метода getTag(). Далее используя метод
((MainActivity)getActivity).setTabFragment(myTag)
мы передаем тег нашего фрагмента нашему вышестоящему активити (вместо MainActivity может быть любой другой активити). А во фрагменте из которого извлекается информация также создаем строку, например to, и присваиваем ей результат метода
((MyActivity)getActivity).getTabFragment().
Далее получаем наш фрагмент:
Fragment* fragment = (Fragment*)getActivity().getSupportFragmentManager().findFragmentByTag(to);
где Fragment* - ваш класс фрагмента к которому вы хотите получить доступ.
Таким образом, получив наш fragment мы можем обращаться к нему напрямую, использовать например вызов метода onCreateView с передачей нужной информации в виде Bundle.
Полностью метод описан здесь http://android-er.blogspot.ru/2012/06/communication-between-fragments-in.html

Создание функции ggplot

Допустим у меня есть данные
data=data.frame(s=c(10,13,17,8), pr=c("a","b","a","b"), m=c(rep(as.Date('01.01.2015','%d.%m.%Y'),2), rep(as.Date('01.02.2015','%d.%m.%Y'),2)), pr2=c("c","d","d","c"))
И я пытаюсь создать функцию которая рисует ggplot в зависимости от col1 - колонка по которой нужно делать fill
plot_function=function(col1){...}
Функция должна возвращать ggplot
ggplot(data = data, aes(x = as.factor(m), y = s/2,fill=col1 ,ymax = max(s/2)*1.1)) + geom_bar(position = "dodge", stat="identity") + geom_text(aes(y=s/4,label=paste(round(s/2,3),"%")),position = position_dodge(.9)) + scale_x_discrete(labels = function(x) format(as.Date(x), "%m/%y")) + xlab("m")
где fill переменная внутри функции.
Пробовал сделать нечто подобное используя aes_string() вместо aes() но не знаю как совместить операции над переменными например s/2 и aes_string()
Так же смотрел lazyeval , который я использовал в подобных ситуациях когда делал функции из dplyr, но не смог понять как его тут применить.
в dplyr я делал вот так
group=function(data,...){
dat1=group_by_(data,.dots = lazyeval::lazy_dots(...)) return(dat1) }
Заранее спасибо за помощь.


Ответ

На основании комментария @ArtemKlevtsov и свои догадок на этот счет в итоге сделал вот так
gr_plot=function(data_12,nm){
i=which(colnames(data_12)==nm)
data_12$var=data_12$s/2 data_12$m=as.factor(data_12$m) j=which(colnames(data_12)=="m") k=which(colnames(data_12)=="var")
return( ggplot(data = data_12, aes_string(x = names(data_12)[j], y = names(data_12)[k],fill=names(data_12)[i]))+ geom_bar(position = "dodge",stat="identity")+ geom_text(aes(y=s/4,label=paste(round(s/2,3),"%")),position = position_dodge(.9)) + scale_x_discrete(labels = function(x) format(as.Date(x), "%m/%y")) + xlab("m")
) }
соответственно достаточно просто нарисовать в различных разрезах
gr_plot(data,"pr")

gr_plot(data,"pr2")

Если у кого то есть идеи как сделать нечто подобное через lazyeval было бы интересно увидеть.

Как можно проанализировать качество Java проекта?

Один мой коллега обратился ко мне с просьбой проанализировать написанный его группой программистов проект. Проект писался в течении 4-х лет группой из 10 программистов, с использованием технологии Spring. Можете ли вы поделиться некоторыми идеями, какие инструменты, методы и классификаторы вы используете для анализа качества написания проектов написанных на Java.


Ответ

"Качество написания проекта", на мой взгляд, складывается из двух вещей:
Низкоуровневой: непосредственно качество кода. Для такой проверки используйте статический анализатор кода, он найдет потенциально проблемные места (логические ошибки в условиях, опасные паттерны и т.д.). Существуют как отдельные тулы, так и встроенные в IDE (например, в IntelliJ Idea). Высокоуровневой: качество проектирование, адекватность архитектуры решения. Такое оценивается только анализом требований и готового решения, и требует немалого опыта. Но позволяет ответить на разные вопросы, например: Не загнется ли проект через полгода от незначительных изменений в требованиях? Сложно ли вносить изменения в существующий код? В какой-то степени это даже более важное качество, чем качество кода, поскольку исправлять ошибки этого уровня очень сложно и дорого.

Несколько вопросов по паттерну MVVM

Навели меня на мысль, что весь мой код является "говнокодом", потому что мои WPF приложения не соответствуют паттерну MVVM. Я начал про это читать, но в интернетах информация изложена слишком сложно для моего понимания. Поэтому я задам несколько вопросов, которые откроют мне глаза (я надеюсь)
Допустим, я создаю UserControl. При этом UserControl.xaml является View, а UserControl.xaml.cs - ViewModel? Или ViewModel - это еще один дополнительный класс, например UserControlViewModel? Я пока склоняюсь ко второму варианту, но не уверен. Если в прошлом вопросе правильным является второй вариант, то где мне создавать DependenceProperties? В UserControl.xaml.cs или в UserControlViewModel? Я пока склоняюсь к первому варианту. Если UserControl содержит команды, которые надо добавить к главному меню окна, в котором его расположили, то как это лучше осуществить, не отклоняясь от MVVM? Причем сделать это надо с иерархией. Первое, что приходит на ум - создать в ресурсах UserControl новое Menu. но при слиянии иерархию надо сохранить. То есть если в главном окне уже есть меню "Файл", и оно используется в контроле, то элементы контрола должны добавиться к элементам этого меню в окне без создания еще одного меню "Файл".
UPD:
И еще, что такое Model?
UPD2:
К примеру, мне надо вывести в ListBox коллекцию экземпляров класса MyClass
public class MyClass { public string Prop1 { get; set; } public string Prop2 { get; set; } }
в виде Prop1(Prop2)
Как мне поступить, чтобы соответствовать MVVM?
Раньше я делал так

Получается, что это неверный подход? Или что?
UPD3:
Еще вопрос. Вью и вью-модель связываются, например, через DataСontext вьюшки (других способов я не знаю). В этом случае вью-модель не имеет параметров у конструктора. А как тогда связать вью-модель и модель?
UPD4:
У меня еще вопрос. Вот есть у меня модель, вью-модель и вью. Вью-модель подписана на изменение свойств модели (хоть через PropertyChanged, хоть через отдельные события). Тогда получится следующее. Во вьюшке чего то меняется (пользователь изменил текст в текстовом поле). Через биндинг это передается в сеттер вью-модели, в которой написано следующее _model.Property = value. Но я ведь подписан на изменение свойств модели. Получается, что модель после изменения Property сообщит вью-модели, что ее свойство изменилось, вью-модель вызовет PropertyChanged и во вьюшке применится это значение в текстовом поле. По сути ничего страшного не произойдет, кроме того, что программа выполнит ЛИШНИЕ ДЕЙСТВИЯ


Ответ

Модель представления - это еще один дополнительный класс. Представление не обязательно должно быть UserControl'ом. Это может быть, например, словарь ресурсов с шаблоном данных для модели представления. Тогда ни о каком code-behind речи быть не может. Свойства зависимости нужно создавать в code-behind контрола (т.е. UserControl.xaml.cs). Это часть представления и модели представления о них знать не нужно. UserControl не должен содержать команды. Он должен привязываться к командам модели представления. Если нужна иерархия, то делайте иерархию команд в модели представления плагина (предполагаю, что вы делаете что-то плагинообразное) и сливайте их с командами модели представления главного окна. Еще я бы посоветовал избавиться от иерархии команд и подумать над тем, как их можно представить плоским списком.
UPD
Я согласен с Discord, потому и посоветовал делать плоский список. Это может быть набор команд в модели представления: OpenFileCommand, SaveFileCommand и т.д. А в представлении это уже будет иерархией: меню файл содержит пункты "открыть" и "сохранить".
Если у вас ситуация, когда пол проекта написана на WinForms, а половина на WPF, то, возможно, ваше решение вполне подходит. Просто после переноса проекта нужно не забыть переделать эту часть.
Когда мы перетаскивали проект в WinForms на WPF, то сначала изменили главное окно приложения: оно научилось работать с плагинами и формировать меню из них. Все компоненты на WinForms мы обернули в WindowsFormsHost А потом уже переделывали плагины на WPF по одному.
Модель - это то, для чего вы делали модель представления (например, какой-нибудь объект из БД). Примерно так: модель - то, что нужно показать пользователю; представление - то, что видит пользователь; модель представления - связующее звено с командами и доп. свойствами, необходимыми для корректной работы представления.
UPD2
С ходу довольно сложно придумать нормально решение, а на практике с именно такой задачей я не сталкивался. Например, вы можете сделать пачку интерфейсов типа:
// команды, расширяющие пункт меню "Файл". interface IFileCommandsProvider { List Commands { get; } }
А потом: если вкладка реализует этот интерфейс, то добавить перечень команд в меню.
Либо подумать над вариантом с чем-то вроде RegionManager'а из Prism
UPD4
В описанном вами случае эти действия выполнять не надо. Если по какой-то причине (например, чтобы повесить атрибуты валидации), вы хотите спрятать свойство модели за свойством модели представления, то в модели представления имеет смысл написать следующий код:
public int Property { get { return _model.Property; } set { if (_model.Property != value) { _model.Property = value; OnPropertyChanged(); } } }
Тогда всю работу со свойством Property внутри модели представления нужно будет осуществлять через свойство модели представления. Т.е. кода _model.Property = value больше нигде не должно встречаться. Тогда вам не нужно будет подписываться на Model.PropertyChanged("Property").

Как временно “приглушить” monit на период развертывания сервиса через ansible?

Есть сервер на linux, на нем работает некий сервис myservice, за сервисом наблюдает monit. Сообщает на почту обо всех изменениях и при необходимости перезагружает сервис.
Есть ansible playbook, который переустанавливает сервис, конфигурирует и перезапускает. И monit тоже конфигурирует и перезапускает при необходимости. Работает это отлично, но плохо то, что при этом monit шлет пачку писем:
service instance пропал service instance появился service instance сменил PID monit перезагрузился
Можно в роли давать monit задачу приостанавливать мониторинг, но об этой задаче он тоже сообщает. Дважды.
- name: monit не наблюдает за myservice shell: monit unmonitor myservice
- name: monit наблюдает за myservice shell: monit monitor myservice
Можно перезапускать сервис из самого monit'a. Тогда письма приходят с менее угрожающими заголовками, вроде Action done myservice. Но всё равно одно или два письма + одно про релоад монита.
- name: Перезапуск myservice через monit shell: monit restart myservice
Я беспокоюсь о том, что это всё сработает как у мальчика, который кричал «Волки!». Все привыкнут, что с почты постоянно валится куча писем и что это нормальный процесс, волноваться не о чем. Поэтому хочу, чтобы штатные работы не приводили ни к каким тревогам вообще.
Можно ли это как-то реализовать на этом стеке технологий? Или я категорически неправ в своих опасениях?


Ответ

Решение
monit
config: /etc/monit/monitrc
set alert {{mail_recipient}} but not on { action, instance }
ansible:
Во всех командах параметр -I нужен, почему — смотри ниже.
В начале установки через monit останавливаем сервис, это считается action
- name: Остановка myservice через monit shell: monit -I stop myservice
Потом производим всю необходимую установку и настройку.
Убеждаемся, что сам monit запущен. Перезагружаем конфиги через сам monit, это событие типа instance
- name: Убедиться, что monit запущен service: name=monit state=started
- name: Перезагрузка конфигов monit shell: monit -I reload
Потом перезагружаем сервис, это считается action
- name: Перезапуск myservice через monit shell: monit -I restart myservice

Конфигурация monit
Получать только определенные события
set alert foo@bar only on { timeout, nonexist }
Получать все события кроме некоторых:
set alert foo@bar but not on { instance }
Подробнее про фильтрацию событий в monit:
https://mmonit.com/monit/documentation/monit.html#Setting-an-event-filter
Оставшиеся проблемы
monit "забывает" команды, отданные после перезагрузки — решено.
Разобрано в отдельном вопросе, здесь я просто добавляю -I к командам. C такой конфигурацией monit перестает сообщать об изменениях собственного instance не только на период развертывания, а вообще. То есть, если он был перезагружен вручную, либо если упал а потом был поднят при развертывании — то сообщения не будет.
Можно оставить только такой конфиг:
set alert {{mail_recipient}} but not on { action }
Но тогда при развертывании все равно будет одно сообщение на почту про sudo monit reload. Безуспешно пробовал такую схему, она не работает.
name: monit - приостановить мониторинг shell: monit unmonitor all name: monit - перезагрузка конфигов shell: monit reload name: monit - возобновить мониторинг shell: monit monitor all

Библиотека для парсинга pdf в текст (android)

Подскажите какую библиотеку можно использовать в Android Studio для парсинга pdf в текст?


Ответ

https://stackoverflow.com/a/6118652/873481
Я использовал itext .jar - хорошая библиотека. Насчет Android Studio - не знаю, думаю, как и в обычном джава-проекте, можно просто присоединить .jar к проекту...

Как настроить всплывающее окно с fancybox после нажатия button с

Есть форма:


Подскажите плз, как после отправки формы открыть окно с блоком
на 5-10 секунд и пропадало, планирую сделать на fancybox
Планирую использовать:
$('#send').submit(function(e) { $.fancybox({ href: '#thx', modal: true }); return false; });
Но открытие так и не происходит....


Ответ

Решил сам: в конце php функции добавил код sleep(5);
а скрипт такой:
$('.send').click(function() { $.ajax({ type: $(this).attr('method'), url: $(this).attr('action'), data: $(this).serialize('#contact'), success: function(data) { $.fancybox({ href: '#thx', openEffect: 'elastic', closeEffect: 'elastic', afterLoad: function() { setTimeout(function() { parent.$.fancybox.close({ closeEffect: 'elastic' }); }, 3000); } }); } }); });
может кому пригодится....

Правильное хранение лайков/дислайков (голосования) в БД

Есть сайт, на котором должна быть организована система голосования (лайк/дислайк). Если записывать в БД информацию в виде номер_записи - id_пользователя, то вроде бы всё хорошо. Но. Возьмем 100 записей и 100 пользователей. Каждый из них проголосует за каждую запись, в итоге в БД будет содержаться 10.000 записей, а это проблема. Почитав немного, изменил таблицу и она стала вида: номер_записи - id_всех_пользователей_которые_голосовали При тех же условиях вместо 10.000 получим всего 100 записей в БД.
Добавление нового id пользователя происходит так:
забираем всю строку из БД, где номер записи равен N SELECT FROM WHERE users_id LIKE '%id_пользователя%' - запрос, чтобы проверить существование уже этого id в строке в случае успешной проверки добавляем в конец строки новый id и заносим в БД новую строку.
Насколько это правильный подход к хранению такого рода информации? Какие есть альтернативы? Готов услышать и принять к сведению.


Ответ

Прикинем, как часто что требуется.
сумма (или две суммы: за и против) по конкретному голосованию – супер-часто – при каждом открытии страницы с этим голосованием. голосовал ли данный юзер за данный опрос? – реже, при приёме нового голоса. кто проголосовал за / против за данный вопрос? – ещё реже, если вообще это открытая инфа. как и где голосовал данный юзер – тоже, вероятно, совсем редко, если вообще.
Итого, текущие суммы храним в каком-нибудь быстром кэше, типа memcached/apc/redis.
При поступлении нового голоса в БД надо проверить, голосовал ли? и сохранить голос + обновить кэшированную сумму. Хорошо иметь отдельную таблицу только для голосов:
id_опроса id_юзера голос_плюс_минус (1 бит)
Основной индекс составной - по обоим id - т.к. будем искать и по вопросу-юзеру (можно ли принять голос - может быть только одна запись с парой qid,uid) и по опросу (кто-как). И ещё индекс только по юзеру (где голосовал).
Да, будет запись в БД и двух индексах на каждый отданный голос. Хоть 10 млн. – это нормально. Каждая запись – два 32-битных целых и 1 бит. Когда проект вырастет – станете горизонтально масштабировать – скажем, id опросов меньше X уедут на доп. MySQL сервер.

Как отобразить символ рубля на версии Android > 4?

На Android > 5.0, все хорошо. Пробовал как мне кажется все советы со stackoverflow, символ либо не отображается, либо отображается квадрат. Использую эмуляторы Genymotion. Вот моя тестовая активность:
public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
TextView textView1 = (TextView)findViewById(R.id.textView1); TextView textView2 = (TextView)findViewById(R.id.textView2); TextView textView3 = (TextView)findViewById(R.id.textView3); TextView textView4 = (TextView)findViewById(R.id.textView4); TextView textView5 = (TextView)findViewById(R.id.textView5);
Typeface typeface = Typeface.createFromAsset(getAssets(), "Roboto-Regular.ttf"); textView1.setTypeface(typeface); textView2.setTypeface(typeface); textView3.setTypeface(typeface); textView4.setTypeface(typeface); textView5.setTypeface(typeface);
String test1 = "100 $"; String test2 = "200 \u20BD"; String test3 = "300 \\u20BD"; String test4 = "400 ₽"; String test5 = "500 ₽";
//textView1.setText(Html.fromHtml(getString(R.string.test_1))); //textView2.setText(Html.fromHtml(getString(R.string.test_2))); //textView3.setText(Html.fromHtml(getString(R.string.test_3))); //textView4.setText(Html.fromHtml(getString(R.string.test_4))); //textView5.setText(Html.fromHtml(getString(R.string.test_5)));
textView1.setText(Html.fromHtml(test1)); textView2.setText(Html.fromHtml(test2)); textView3.setText(Html.fromHtml(test3)); textView4.setText(Html.fromHtml(test4)); textView5.setText(Html.fromHtml(test5));
//textView1.setText(test1); //textView2.setText(test2); //textView3.setText(test3); //textView4.setText(test4); //textView5.setText(test5); } }
Что я делаю не так?


Ответ

Возьмите последнюю версию шрифта Roboto Regular из официального репозитория: http://github.com/google/roboto/tree/master/out/RobotoTTF
На сайте Android design сейчас выложена его устаревшая версия, в ней нет начертаний большинства символов валют.

Синхронизация проектов Eclipse через git

Как лучше синхронизировать проекты Eclipse между разными машинами на разных ОС?
Принципы работы git ясны, репозиторий имеется, однако есть некоторые сложности:
Проекты эклипса на разных ос конфигурируются по-разному. Поэтому все служебные файлы приходится заносить в gitignore, так велит gitignore.io Импортировать проект эклипса без служебных файлов на другой машине уже не получается. Импортируется обычный проект, без buildpath и прочих плюшек. Конвертировать его в java проект невозможно.
Каким образом можно наладить систему, чтобы на каждой машине был проект?


Ответ

Решение из англоязычного раздела.
Импортируйте, как обычный проект Обратите внимание, что импортируемые данные не являются проектом Eclipse (нет build path) Откройте/создайте.project файл в папке импортированного проекта. Перейдите во раздел source Найдите и измените на org.eclipse.jdt.core.javanature и сохраните файл Правый клик в Eclipse на папке src, перейдите в Build Path... и кликните Use as Source Folder
https://stackoverflow.com/a/32407205/5244594
Для большего теоретического удобства в будущем стал работать с проектом maven, а не с проектом Eclipse. Больше универсальности и переносимости. При импорте проекта maven следует импортировать, как Existing Maven Project. Eclipse сам определяет, что проект принадлежит git.
В итоге мы имеем проект с автоматическим контролем зависимостей, находящийся в git-репозитории, что позволяет синхронизировать проект не только между машинами, но и между различными IDE, поддерживающими maven.

Правильно ли помещать логику ввода данных с консоли в конструктор?

Задание: "Реализовать программу учета среднесуточной температуры на протяжении месяца. Ввод данных реализовать с консоли." Что правильнее:
Поместить в конструктор по умолчанию логику ввода данных с консоли со всеми валидациями? Создать отдельный метод для ввода данных, затем создавать объект класса, и к нему применять этот метод?
У меня сейчас вот так в конструкторе:
public TemperatureRecords() { System.out.println("Введите название месяца:"); setMonth(input.nextLine().toLowerCase()); while (getDaysAmount()!=0) { System.out.printf("Введите температуру %d числа:%n", temp);
try { setTemperature(input.nextInt()); setDaysAmount(getDaysAmount()-1); } catch (Exception e) { System.out.println("Ошибка!"); input.skip(".*"); } } }


Ответ

Определённо, нет. То, как это реализовано у вас - явно неправильно. В вашем случае конструктор класса и сам класс зависят от консольного ввода. Вообще зависимости между классами - вещь не очень хорошая, а зависимости настолько явные и того хуже. В данном случае мы имеем вот какую проблему: ваш класс не может работать без консоли, хотя не имеет к ней ни малейшего отношения. Представьте, что вам понадобилось использовать этот класс в каком-то другом приложении, где взаимодействие с пользователем происходит не через консоль, а каким-то другим способом (страница в браузере, форма десктопного приложения или как-то ещё). Вы не сможете корректно создать экземпляр вашего класса, и конструктор потребуется переписывать (или добавлять ещё один) чтобы он мог принимать данные не из консоли. Это говорит о том, что конструктор должен принимать необходимые данные в качестве параметров, класс можно будет безболезненно использовать о куда угодно. Как-то так:
public TemperatureRecords(String month, int[] temperatureData) { setMonth(month); for(int value : temperatureData) { setTemperature(value); setDaysAmount(getDaysAmount()-1); } }
Дело даже не в том, что конструктор стал вдвое короче (вырезанный из него код все равно должен будет использоваться, только в другом месте), а в том, что он во-первых, стал проще, а в-вторых, и в-главных, он теперь получает только те данные, которые ему нужны, знать ничего не знает ни о каких классах, которые не имеют к нему отношения и, следовательно, может быть вызван откуда угодно.
Логику же получения данных от пользователя и их валидацию правильнее будет возложить на другой код, разделив тем самым логику вашего класса и логику получения для него данных (да-да, старый принцип "разделяй и властвуй" никто не отменял).

проблема с наследованием через конструктор

пример наследования:
есть 2 конструктора: Game, Level. на их основе я создаю 2 объекта, таким образом, чтобы level наследовался от game:
var Game = function(parentGameElementTag) { this.parentGameElementTag = parentGameElementTag; this.gameElementId = 'game'; this.levelObj = new Level();
this.init(); };
Game.prototype = { init: function() { $('

').appendTo(this.parentGameElementTag); } };
var Level = function() { var self = this;
this.fieldElementId = 'field'; this.levelScreenDisplay('body'); };
//Level.prototype = Game; Level.prototype = Object.create(Game.prototype);
Level.prototype = {
levelScreenDisplay: function(parentElementTag) { $('
Уровень: ' + this.level + '
').appendTo(parentElementTag);
setTimeout(function() { $('
Нажмите любую клавишу для старта
').appendTo('#levelBeginLabel');
document.onkeypress = function() { document.onkeypress = undefined; $('#levelBeginLabel').remove(); }; }, 1000); } };
var app = new Game('body');
в результате на странице должен выводиться номер уровня. которого нет в level, но который есть в game. а благодаря наследованию он должен найтись. но не находится. в чём я ошибаюсь?


Ответ

Основная проблема в том, что свойства level нет ни в одном из классов поэтому всегда выводится undefiend
Кроме того в данном случае не нужно наследование. Проще указать это свойство через конструктор.
var Game = function(parentGameElementTag) { this.parentGameElementTag = parentGameElementTag; this.gameElementId = 'game'; this.levelObj = new Level(1); this.init(); }; Game.prototype = { init: function() { $('

').appendTo(this.parentGameElementTag); } }; var Level = function(level) { var self = this; this.level = level; this.fieldElementId = 'field'; this.levelScreenDisplay('body'); }; Level.prototype = { levelScreenDisplay: function(parentElementTag) { $('
Уровень: ' + this.level + '
').appendTo(parentElementTag); setTimeout(function() { $('
Нажмите любую клавишу для старта
').appendTo('#levelBeginLabel'); document.onkeypress = function() { document.onkeypress = undefined; $('#levelBeginLabel').remove(); }; }, 1000); } }; var app = new Game('body'); .level_begin_label { position: absolute; top: 0; left: 0; right: 0; bottom: 0; z-index: 1000; background: #000; padding-top: 20px; color: #fff; text-align: center; font: 20px arial, sans-serif; } .any_key_invitation { margin-top: 10px; font-size: 16px; } .game { /* position: absolute; top: 0; left: 0; right: 0; bottom: 0;*/ z-index: 10; position: relative; background: #000; width: 300px; height: 100%; margin: 0 auto; padding-top: 40px; color: #fff; }
UPDATE: обновление после комментария. В данном случае проще всего сохранить ссылку на Game внутри создаваемого объекта Level.
var Game = function(parentGameElementTag) { this.parentGameElementTag = parentGameElementTag; this.gameElementId = 'game'; this.level = 1; //например this.levelObj = new Level(this); // передаем ссылку game объекта в конструктор для уровня this.init(); }; Game.prototype = { init: function() { $('
').appendTo(this.parentGameElementTag); } }; var Level = function(game) { var self = this; this.level = game.level; // можно опустить эту строучку и получать значение через this.game.level this.game = game; this.fieldElementId = 'field'; this.levelScreenDisplay('body'); }; Level.prototype = { levelScreenDisplay: function(parentElementTag) { $('
Уровень: ' + this.level + '
').appendTo(parentElementTag); setTimeout(function() { $('
Нажмите любую клавишу для старта
').appendTo('#levelBeginLabel'); document.onkeypress = function() { document.onkeypress = undefined; $('#levelBeginLabel').remove(); }; }, 1000); } }; var app = new Game('body'); .level_begin_label { position: absolute; top: 0; left: 0; right: 0; bottom: 0; z-index: 1000; background: #000; padding-top: 20px; color: #fff; text-align: center; font: 20px arial, sans-serif; } .any_key_invitation { margin-top: 10px; font-size: 16px; } .game { /* position: absolute; top: 0; left: 0; right: 0; bottom: 0;*/ z-index: 10; position: relative; background: #000; width: 300px; height: 100%; margin: 0 auto; padding-top: 40px; color: #fff; }

Cкачать (fetch) с GitLab содержимое запроса на слияние (merge request)

Сервер Gitlab, организую работу через запросы на слияние (merge request, pull request).
При создании запроса хотелось бы иметь URL, из которого Jenkins смог бы выкачивать последний коммит ветки, которая предлагается к слиянию.
Есть ли возможность в Gitlab получить такой URL?
какой-нибудь alias к ветке, предлагаемой к слиянию? автоматически создаваемый предварительный коммит? (т.е. что бы получилось, если прямо сейчас нажать кнопку Merge Request?
Знаю, что-то подобное возможно в Gitlab CI и GitHub CI, на этих коммитах даже тесты прогоняются. Поэтому возможен и третий вариант:
Работать с Jenkins как с Gitlab CI?
Перейти полностью на Gitlab CI - не вариант, это будут неоправданные затраты.


Ответ

автоматически создаваемый предварительный коммит? (т.е. что бы получилось, если прямо сейчас нажать кнопку Merge Request?
Фича пока не реализована, можно проголосовать.
какой-нибудь alias к ветке, предлагаемой к слиянию?
Реализовано. На каждый merge request гитлаб создаёт внутри себя отдельный указатель в refs/merge-requests. Нужно просто настроить свой репозиторий, чтобы при git fetch забирать эти указатели.
Открываем .git/config, находим в нём блок, соответствующий репозиторию.
[remote "origin"] url = https://gitlab.com/gitlab-org/gitlab-ce.git fetch = +refs/heads/*:refs/remotes/origin/* Добавляем в него строку +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*. Теперь должно выглядеть так:
[remote "origin"] url = https://gitlab.com/gitlab-org/gitlab-ce.git fetch = +refs/heads/*:refs/remotes/origin/* fetch = +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/* Обновляем данные:
$ git fetch origin From https://gitlab.com/gitlab-org/gitlab-ce.git * [new ref] refs/merge-requests/1/head -> origin/merge-requests/1 * [new ref] refs/merge-requests/2/head -> origin/merge-requests/2 Теперь можно создать новую локальную ветку, отслеживающую соответствующий merge request.
$ git checkout merge-requests/1 Branch merge-requests/1 set up to track remote branch merge-requests/1 from origin. Switched to a new branch 'merge-requests/1'
Примеры взяты из документации GitLab. Там же есть более подробные инструкции.