Страницы

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

понедельник, 3 декабря 2018 г.

Запрет push в ветку master

Как сделать, чтобы обновить ветку master могли только путём merge.
Итого с веткой master могут выполняться только действия: merge fetch pull
Сейчас же любой джуниор может "повесилить" всю команду. Да откатили, да наругали - но не он первый, не он последний.
Если на сервер залить какой-то скрипт проблема будет, то можно же наверно и локально устанавливать с bash'ем скрипт, который запретит делать "беду"


Ответ

Используйте модель пулл-реквестов («Fork + Pull») вместо модели «Общего репозитория»(The Shared Repository Model).
Гитхаб рекомендует Using pull requests

Unicode и char. Подскажите как корректно заменить char на wchar_t?

Есть игра "Виселица", которая написана для работы только с английскими символами. Хочу добавить русские слова. Не получается заменить тип char в программе на другие, чтобы была возможность ввода и обработки символов кириллицы.
char guess;
Поискав похожие темы, понял что, символы Unicode кодируются двумя байтами, а тип char может помещать один. Поэтому в игре вместо кириллицы отображаются ромбы со знаками вопросов. Подскажите, как правильно заменить char на wchar_t, чтобы компилятор не выдавал ошибку в строках сравнения THE_WORD[i] == guess и soFar[i] = guess;
// update soFar to include newly guessed letter for (unsigned int i = 0; i < THE_WORD.length(); ++i) { if (THE_WORD[i] == guess) { soFar[i] = guess; } }
Система Ubuntu 14.04, компилятор GCC 4.9.1 20140922 (Red Hat 4.9.1-10), 64 bit Qt Creator 3.6.0 Based on Qt 5.5.1
Вот весь код
// Hangman // The classic game of hangman
#include #include #include #include #include #include
using namespace std;
int main() { // set-up const int MAX_WRONG = 8; // maximum number of incorrect guesses allowed
vector words; // collection of possible words to guess words.push_back("монитор"); words.push_back("телескоп"); words.push_back("смартфон");
srand(static_cast(time(0))); random_shuffle(words.begin(), words.end()); const string THE_WORD = words[0]; // word to guess int wrong = 0; // number of incorrect guesses string soFar(THE_WORD.size(), '*'); // word guessed so far string used = ""; // letters already guessed
cout << "Welcome to Hangman. Good luck!
";
// main loop while ((wrong < MAX_WRONG) && (soFar != THE_WORD)) { cout << "

You have " << (MAX_WRONG - wrong); cout << " incorrect guesses left.
"; cout << "
You've used the following letters:
" << used << endl; cout << "
So far, the word is:
" << soFar << endl;
char guess; cout << "

Enter your guess: "; cin >> guess;
while (used.find(guess) != string::npos) { cout << "
You've already guessed " << guess << endl; cout << "Enter your guess: "; cin >> guess; }
used += guess;
if (THE_WORD.find(guess) != string::npos) { cout << "That's right! " << guess << " is in the word.
";
// update soFar to include newly guessed letter for (unsigned int i = 0; i < THE_WORD.length(); ++i) { if (THE_WORD[i] == guess) { soFar[i] = guess; } } } else { cout << "Sorry, " << guess << " isn't in the word.
"; ++wrong; } }
// shut down if (wrong == MAX_WRONG) cout << "
You've been hanged!"; else cout << "
You guessed it!";
cout << "
The word was " << THE_WORD << endl;
return 0; }


Ответ

Итак, благодаря помощи участников сайта: @gbg ,@avp, @Abyx, @ixSci и особенно @VladD удалось решить вопрос мультиязычности программы 'Виселица'. Привожу полный код решения и комментарий к нему.
// Система Ubuntu 14.04, компилятор GCC 4.9.1 20140922 (Red Hat 4.9.1-10), 64 bit // Qt Creator 3.6.0 Based on Qt 5.5.1
// Классическая игра 'Виселица' #include #include #include #include #include #include #include // заголовочный файл настройки локализации // содержит функции для работы с локализацией программы. // Если не включить этот файл и не использовать функцию locale, то // русские надписи будут выводиться в виде нечитабельных иероглифов
using namespace std;
int main() { locale::global(locale("")); // ф-ция для установки локали // http://ru.cppreference.com/w/cpp/locale/locale/global
// первоначальные настройки const int MAX_WRONG = 8; // максимальное количество попыток vector words; // коллекция слов для отгадывания words.push_back(L"монитор"); words.push_back(L"терминал"); words.push_back(L"смартфон");
srand(static_cast(time(0))); // засев поля случайных чисел random_shuffle(words.begin(), words.end()); // перемешивание слов const wstring THE_WORD = words[0]; // слово для отгадывания int wrong = 0; // количество неправильных попыток wstring soFar(THE_WORD.size(), '*'); // угадываемое слово на данный момент wstring used = L""; // использованные буквы wcout << L"Добро пожаловать в 'Виселицу'. Удачи!
";
// основная игра while ((wrong < MAX_WRONG) && (soFar != THE_WORD)) { wcout << L"
У Вас остается " << (MAX_WRONG - wrong) << L" попыток.
"; wcout << L"
Вы использовали следующие буквы:
" << used << "
"; wcout << L"
Пока слово:
" << soFar << "
";
wchar_t guess; wcout << L"

Введите букву: "; wcin >> guess;
while (used.find(guess) != wstring::npos) { wcout << L"
Вы уже называли букву '" << guess << "'
"; wcin >> guess; } used += guess; if (THE_WORD.find(guess) != wstring::npos) { wcout << L"Верно! '" << guess << L"' есть в слове.
";
// обновляем слово угаданными буквами for (unsigned int i = 0; i < THE_WORD.length(); ++i) { if (THE_WORD[i] == guess) { soFar[i] = guess; } } } else { wcout << L"Извините, буквы '" << guess << L"' нет в слове.
"; ++wrong; } }
// конец игры if (wrong == MAX_WRONG) { wcout << L"
Вас повесили!"; } else { wcout << L"
Вы угадали!"; } wcout << L"
Слово было '" << THE_WORD << L"'
"; return 0; }
Итак, основные изменения в программе, чтобы корректно отображались и обрабатывались символы кириллицы. 1 - добавить заголовочный файл locale 2 - использовать функцию установки локали locale::global(locale("")); 3 - Заменить везде char на wchar_t, string на wstring, cin на wcin, cout на wcout (и главное, то что я немного упускал из виду,- строку на вывод отправлять не просто "строка", а L"строка" !!!) Вот и весь секрет работы с Юникодом в С++ Все полезные замечания обязательно учту.

Генерация случайной строки со сбалансированными скобками

Возникла тут проблемка генерить случайную строку со сбалансированными скобками. Т.е. строка abc(def(g)h)i - сбалансирована, а abc(def(g)hi и abc)(def)g - нет. Код есть, и он работает нормально но есть одна проблемка: почти все строки заканчиваются закрывающими скодками. Где я вижу проблему, и собственно вопрос - под кодом.
char * create_balanced_cstring(const char *alphabet, // строка нейтральных символов (напр abcdefg...) char obr, char cbr, // открывающая и закрывающая скобки unsigned lmin, unsigned lmax) // мин и макс длина строки { if (strchr(alphabet, obr) || strchr(alphabet, cbr)) return 0; if (lmin > lmax || lmin == 0) return 0;
int lenalph = strlen(alphabet); // длина "алфавита" нейтральных символов int length = rand() % (lmax - lmin + 1) + lmin; // длина генерирующейся строки char *s = (char*) malloc(length + 1); if (!s) return s;
int opened = 0; // кол-во открытых скобок int just_opened = 0; // флаг для избегания фрагментов '()' char curchar; // текущий символ в строке for (int i = 0; i < length; ++i) { if (opened == length - i) curchar = cbr; else { if (opened + i + 2 >= length) curchar = alphabet[rand() % lenalph]; else { int r = rand() % length; if (r < opened * 3 && !just_opened) curchar = cbr; else if (r > 2 * length / 3 - opened) curchar = obr; else curchar = alphabet[rand() % lenalph]; } }
if (curchar == obr) { ++opened; just_opened = 1; } else { just_opened = 0; if (curchar == cbr) --opened; }
s[i] = curchar; } s[length] = '\0';
return s; }
Проблема, ИМХО, тут:
int r = rand() % length; if (r < opened * 3 && !just_opened) curchar = cbr; else if (r > length - opened) curchar = obr; else curchar = alphabet[rand() % lenalph];
т.е. с выбором в (условно) начале строки - открывать скобку, закрывать, или ставить случайный символ. Хочется, чтобы вероятность открыть скобку увеличивалась, если их открыто мало и наоборот, закрыть - увеличивалась если открыто много и наоборот. Просто поиграться с коэффициэнтами? Текущие *3 и 2/3 - эмпирические, так вроде еще более-менее.
Т.е. в итоге нужно по 3-м параметрам (длина строки l, текущая позиция i и количество незакрытых в этой позиции скобок o) сделать распределение вероятности выбора открывающей/закрывающей скобки или "нейтрального" символа (не скобки) в данной позиции


Ответ

Посмотрите Кнута, "Искусство программирования", т. 4А, стр. 511 русского издания, алгоритм W - равномерно распределенные случайные строки вложенных скобок. Алгоритм генерирует случайную строку корректно вложенных скобок для заданного их количества.
Растыкать случайным образом 2n мест для скобок в строке, сгенерировать строку скобок и вставить на подготовленные места - не подойдет?

Обратные ссылки в путях файлов Grunt

Здравствуйте. Возникло затруднение в обработке путей в Grunt, а именно задачу concat: как передать что-то из найденных путей в значение целевого пути? Есть примерно такая структура проекта:
src -js --Core ---Core.js ---Something.js ---0_Header.js --FileLoader ---ExternalInterface.js ---Core.js ---Helper.js
Необходимо чтобы concat собирал примерно вот так:
build -js --Ext ---Core ----Core.min.js ---FileLoader ----FileLoader.min.js
Здесь подошло бы что-то вроде этого:
concat: { *** files: { 'build/js/Ext/$1/$1.min.js': ['src/js/(*)/**/*.js'] } *** }
Но это не работает. Отдельно прописывать каждый модуль, когда явно можно автоматизировать - глупо. Как правильно прописать? Благодарю.


Ответ

Как вариант - сформировать нужный объект руками:
var files = {}; grunt.file.expand("./src/js/*").forEach(function (dir) { var dirname = dir.replace(/^.*[\\\/]/, ''); files['build/js/Ext/' + dirname + '.min.js'] = ['src/js/' + dirname + '/**/*.js']; });
И использовать в конфигурации для concat:
grunt.initConfig({ concat: { dist: { files: files } } });
Альтернатива - использовать возможность переименовать dst (регулярка на скорую руку, не учитывает backslah-и):
grunt.initConfig({ concat: { dist: { files:[{ expand: true, src: ['src/js/**/*.js'], rename: function (dst, src) { return src.replace(/src\/js\/([^\/]*).*/, 'build/js/Ext/$1/$1.min.js'); } }] } } });

Как изменить символы в шаблоне, заменив {{ и }} на <% и %> ? -Golang

Есть хандлер
func Handler(w http.ResponseWriter, r *http.Request) { var templates = template.Must(template.ParseGlob("Templates/Main/*/*")) var doc bytes.Buffer err := templates.ExecuteTemplate(&doc, "indexPage", nil) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } //templates.Delims("<%", "%>").Funcs(Main_TemplateFuncs).Parse("<%шаблон %>") fmt.Fprintln(w, &doc) }
Мне нужно переназначить символы {{ и }} , так как я использую в angularjs такие же символы. Есть функция templates.Delims("<%", "%>"), которая переназначет их, но она работает, если после неё в Parse закинешь текст. А у меня идёт множество файлов template.Must(template.ParseGlob("Templates/Main//")) и как мне их обработать, заменив стандартную обработку {{ и }} на <% и %> ?


Ответ

templ := template.New("templ") //поменять символы templ.Delims("<%", "%>") //и парсить туда var templates = template.Must(templ.ParseGlob("Templates/Main/*/*"))

Послать сообщение в skype чат используя python

Необходимо написать программу на Python для отправления сообщений в чат Skype. Skype4Py не подходит из-за того, что стоит 64-битный Python.
Существуют ли какие-либо альтернативы для работы со Skype, помимо Skype4Py, и есть ли Skype API для отправки сообщений?


Ответ

Скайп-бот может послать сообщение, используя REST API
POST /v2/conversations/8:alice/activities HTTP/1.1 Host: apis.skype.com Authorization: Bearer { "message": {"content" : "Hi! (wave)"} }
например чтобы послать message строку skypeid пользователю на Питоне:
#!/usr/bin/env python2 import json from urllib2 import urlopen, Request
def send_message(message, skypeid, token, host='apis.skype.com'): url = 'https://{host}/v2/conversations/8:{skypeid}/activities'.format(**vars()) headers = dict(Authorization='Bearer ' + token) data = json.dumps(dict(message=dict(content=message))).encode() urlopen(Request(url, data, headers)).close()
где token можно получить с помощью другого http POST запроса:
from urllib import urlencode
def get_access_token(client_id, client_secret): # from messaging/auth-service.js in skype-sdk # NOTE: unlike the documented way in /skype/bots/docs/; # this approach works for me url = 'https://login.microsoftonline.com/common/oauth2/v2.0/token' data = urlencode(dict(client_id=client_id, scope='https://graph.microsoft.com/.default', grant_type='client_credentials', client_secret=client_secret)).encode() return json.loads(urlopen(url, data).read().decode())['access_token']
access_token можно кэшировать expires_in секунд.
Чтобы получить client_id, client_secret необходимо зарегистрировать приложение со своей microsoft учётной записью и создать пароль
Затем сам Skype бот нужно также зарегистрировать, чтобы получить ссылку, по которой можно добавить бота в Skype-контакты (до публикации бота, по этой ссылке его можно найти).
Чтобы получить ответные сообщения нужно указать при создании Skype бота https webhook. Для теста, можно ngrok http 8000 использовать, который напечает url, который можно как публичный webhook указать. При этом достаточно локально http (не https) сервер запустить, который json может принимать, на указанном 8000 порту, например:
#!/usr/bin/env python3 from aiohttp import web # $ pip install aiohttp
async def handle(request): messages = await request.json() for message in messages: print(message) return web.HTTPCreated() # 201
app = web.Application() app.router.add_route('POST', '/v1/chat', handle) web.run_app(app, host='localhost', port=8000, ssl_context=None)
В тему статья на Хабрахабр: Как создать своего бота для Skype. Что не написано в документации

Одновременно работающий код js и jquery [закрыт]

Написал код слайдера на javascript и мне понадобилась функция клонирования из jquery Как заставить их работать вместе без проблем?


Ответ

Может быть стоит использовать elem.cloneNode(true) вместо JQ? Например так:
"use strict";
var main1 = document.querySelector("#main1"); var forBlockBigLeft = document.querySelector("#forBlockBigLeft");
var new_elem = main1.cloneNode(true); main1.parentNode.insertBefore(new_elem, forBlockBigLeft.nextSibling);

Размещение нескольких элементов в видимой области ViewPager

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


Ответ

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



Это даст нам возможность скроллить карды по горизонтали.
Теперь нужно изменить ширину кардов так, чтобы на экран помещалось два карда. Для этого можно, например, унаследоваться от Card и переопределить onMeasure
public class MyCard extends Card { // …
@Override protected void onMeasure(int widthMeasureSpec, final int heightMeasureSpec) {
final View parentScrollView = ((View)(getParent().getParent()));
if (parentScrollView != null) { if (parentScrollView instanceof HorizontalScrollView) { widthMeasureSpec = parentScrollView.getMeasuredWidth() / 2; } } setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); } }
Останется по событию скролла вычислить ближайшую позицию скролла, в которой на экране будут отображаться два карда целиком и вручную доскроллить через HorizontalScrollView.fullScroll(…)

Межкомпонентная связь React: как передавать данные между компонентами?

Здравствуйте! Вопрос касается связи между компонентами React,а именно: передача данных из одного компонента в другой.
Пусть есть страница , у которой есть массив объектов items. Для каждого элемента items создается компонент
Код Layout.jsx:
class Layout extends Component { renderItems() { var items = [ {name: 'Ivan', _id: '1'}, {name: 'Petya', _id: '2'} ];
return items.map( (each) => { return ( ); }); }
render() { return (

{this.renderItems}
); } }
Код Item.jsx:
class Item extends Component { render() { return (
{this.props.each.name}
); } }
Пусть теперь я хочу реализовать по щелчку на каждый вывод в консоль его _id. Сделать это внутри самого не составляет никакого труда:
Новый код Item.jsx:
class Item extends Component { printId() { console.log(this.props.each._id); }
render() { return (
{this.props.each.name}
); } }
Но как быть, если нужно реализовать кнопку "Показать _id" снаружи, то есть в ?
Допустим, внутри каждого добавим checkbox. Если этот чекбокс отмечен галочкой как selected, то при нажатии кнопки 'Показать _id' в консоль выводятся _id всех отмеченных Itemов.
Но как передать _id отмеченных Itemов в ?
Заранее благодарен за ответы.


Ответ

Ответ нашелся сразу в документации, спасибо @AlexeyTen за наводку. Пришлось помучиться, однако решение готов и оно ниже.
При вызове функции из компонента someFunction.bind(this) мы можем передавать любое количество аргументов: someFunction.bind(this, arg1, arg2, ...). В этом и заключается ответ.
Для примера выше: добавим функцию printId в компонент и навесим на компонент вызов printId по событию onClick. В качестве аргумента в функцию будем передавать текущий _id элемента. Новый код Layout.jsx:
class Layout extends Component { printId(id) console.log(id);
renderItems() { var items = [ {name: 'Ivan', _id: '1'}, {name: 'Petya', _id: '2'} ];
return items.map( (each) => { const eachId = each._id; return ( ); }); }
render() { return (

{this.renderItems}
); } }
Однако, код выше не будет работать. Причина в том, что это не настоящий DOM-элемент, соответственно и события OnClick у него быть не может. В строке onCLick является обычным props. Для того, чтобы этот код работал, как ожидается, нужно внутри компонента у настоящего DOM-элемента прописать передачу настоящему onClick нашу функцию из props
class Item extends Component { render() { return (
{this.props.each.name}
); } }
Теперь все работает как надо.

На что влияет адрес хоста у создателя подпрограммы в MySQL?

На что влияет адрес хоста у создателя подпрограммы в MySQL? Например, при создании подпрограммы (хранимой процедуры, функции, триггера и т.д.) определяется создатель подпрограммы (DEFINER):
CREATE DEFINER = 'admin'@'localhost' PROCEDURE p1() SQL SECURITY DEFINER BEGIN UPDATE t1 SET counter = counter + 1; END;
На что тогда влияет адрес? Например, что бы изменилось, если бы вместо 'admin'@'localhost' тут было 'admin'@'%'?


Ответ

DEFINER просто говорит базе, какой контекст безопасности использовать при выполнении процедуры. Если он стоит как DEFINER - привилегии берутся для аккаунта, который создал процедуру, а если стоит INVOKER - то тогда привилегии, как у того, кто вызвал.
CREATE DEFINER = 'admin'@'localhost' PROCEDURE p1() SQL SECURITY DEFINER BEGIN UPDATE t1 SET counter = counter + 1; END;
Любой пользователь, который имеет привилегию EXECUTE на над процедурой p1 может вызвать ее с помощью оператора CALL. Однако, когда p1 выполняется, она делает это в контексте безопасности DEFINER и, следовательно, выполняется с привилегиями 'admin'@'localhost' , учетной записи, указанной в атрибуте DEFINER. Эта учетная запись должна иметь привилегию EXECUTE для p1 , а также UPDATE привилегии для таблицы t1 . В противном случае, процедура не выполняется из-за отсутствия достаточных привилегий.
Адрес говорит вам о том, что будут использованы привелегии определенные для пользователя 'admin'@'localhost. Тоесть пользователя admin который подключается с localhost, в MYSQL разграничение доступа осуществляется по имени пользователя и адресу с которого идет подключение, для пользователя admin с localhost можно установить GRANT ALL а для других хостов только SELECT например.
Пользователи 'admin'@'localhost' и 'admin'@'%' - это совершенно разные аккаунты.

Прогресс скроллинга страницы. Как сделать?

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


Ответ

var bar = $('#bar'), $window = $(window), docHeight = $(document).height(), winHeight = $window.height(), baseX = docHeight - winHeight; $window.scroll(function(e) { var x = ($window.scrollTop() / baseX) * 100; bar.css({'width': + x + '%'}); }); body{ height:4000px; } ul { list-style-type: none; padding: 0; margin: 0; overflow: hidden; } a { text-decoration: none; } ul li { display: block; float: left; } ul li a { display: block; padding: 1rem 2rem; font-family: sans-serif; } .nav { display: block; width: 100%; border-bottom: 2px solid #ccc; position: relative; position: fixed; } #bar{ position:absolute; left: 0; bottom: -2px; background-color:red; width: 0px; height: 2px; }​


Вариант с якорями:
var bar = $('#bar'), $window = $(window), docHeight = $(document).height(), winHeight = $window.height(), baseX = docHeight - winHeight; var lastId, topNav = $(".nav"), topNavHeight = topNav.outerHeight(), link = topNav.find("a"); scrollItems = link.map(function(){ var item = $($(this).attr("href")); if (item.length) { return item; } }); $window.scroll(function(e) { var x = ($window.scrollTop() / baseX) * 100; bar.css({'width': + x + '%'}); var fromTop = $(this).scrollTop()+topNavHeight; var cur = scrollItems.map(function(){ if ($(this).offset().top < fromTop) return this; }); cur = cur[cur.length-1]; var id = cur && cur.length ? cur[0].id : ""; if (lastId !== id) { lastId = id; link .parent().removeClass("active") .end().filter("[href='#"+id+"']").parent().addClass("active"); } }); body{ height:4000px; padding-top: 5rem; } ul { list-style-type: none; padding: 0; margin: 0; overflow: hidden; } a { text-decoration: none; } ul li { display: block; float: left; } ul li a { display: block; padding: 1rem 2rem; font-family: sans-serif; } .nav { display: block; width: 100%; border-bottom: 2px solid #ccc; position: relative; position: fixed; top: 0; } #bar{ position:absolute; left: 0; bottom: -2px; background-color:red; width: 0px; height: 2px; } .box { height: 20rem; padding: 2rem; line-height: 1.5rem; } .active a{ background: red; color: #fff; }
1 Lorem ipsum dolor sit amet, consectetur adipisicing elit. A, excepturi.
2 Lorem ipsum dolor sit amet.
3 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Temporibus, at debitis! Fuga, architecto, illum. Deleniti optio voluptatibus suscipit veniam, dicta.

Отучить KDE автозапускать последние приложения

Задача такая: отучить KDE автостартовать приложения, которые были запущены в предыдущей сессии. Сами приложения не прописаны в автозапуске, KDE их запускает сам. Искал по всем настройкам, в гугле, ответа не нашел. Как отучить KDE автозапускать последние приложения?


Ответ

Оказалось, эта настройка запрятана в "Управлении сеансами", что в разделе "Запуск и завершение". Мне и в голову не могло придти искать эту функцию там, так как я считал, что сеансы связаны исключительно с входом нескольких пользователей в систему. Итого,что бы отключить эту фитчу идем в "Параметры системы" -> "Запуск и завершение" -> "Управление сеансами" и ставим "Начинать с пустого сеанса".

Масштабирование интерфейса WPF

Было разработано приложение с использованием WPF.
Заказчик использует приложение на планшете и интерфейс мелковат для быстрой работы, требуется увеличить все элементы, ну скажем, на 50%.
Как сделать это быстро и с меньшими затратами? В каждом Window применить к контейнеру компоновки трансформацию Scale в RenderTransform? Попробовал сделать это на примере одного из Window - окно и не знает, что содержимое увеличилось и оно в окно не влезает...
Как всё-таки правильно это сделать? На что при этом обратить внимание? А, может быть, есть способ сделать масштабирование динамическим с возможностью смены коэффициента во время работы (при работе с мышью ведь увеличение и не требуется)?


Ответ

Ну, если решать проблему так, как вы хотите (масштабированием интерфейса), то подойдёт следующая идея. Пусть вы увеличиваете всё в k раз (у вас k = 1.5). Пишем так:



(С удивлением обнаружил, что RenderTransform перемещает область hit test.)

Однако мне кажется, что это не идеальное решение. Дело в том, что простое скалирование интерфейса не поможет. Майкрософт пробовала в ранних версиях Windows Phone скалирование десктопных интерфейсов, и отказалась от этого: при таком подходе страдает usability.
Когда у вас мало места на экране, вы захотите не скалировать всё, а расположить элементы по-другому. Поэтому лучше следовать опыту Microsoft, и сделать для планшетов отдельный интерфейс, похожий на основной, но «заточенный» под меньший размер экрана и тач-управление. Будет выглядеть намного профессиональнее.

Дополнение: Если вам нужно менять размер в зависимости от разных обстоятельств, проще всего сделать его параметром. Это делается так:
В MainWindow кладём DependencyProperty типа double, назовём его ScalseFactor. Значение по умолчанию — 1.0
public double ScaleFactor { get { return (double)GetValue(ScaleFactorProperty); } set { SetValue(ScaleFactorProperty, value); } }
public static readonly DependencyProperty ScaleFactorProperty = DependencyProperty.Register( "ScaleFactor", typeof(double), typeof(MainWindow), new PropertyMetadata(1.0)); Вместо константы 1.5 в ScaleY прописываем привязку:
{Binding ScaleFactor, ElementName=Main}
(даём окну имя Main, чтобы было проще привязывать). Для привязки ColumnDefinition нам нужно вычесть единицу и перейти от double к типу GridLength, поэтому используем конвертер. Для начала определим его:
class RestGridLengthConverter : IValueConverter { public object Convert(object value, Type tt, object parameter, CultureInfo ci) { return new GridLength((double)value - 1, GridUnitType.Star); }
public object ConvertBack(object value, Type tt, object parameter, CultureInfo ci) { throw new NotImplementedException(); } }
Кладём в ресурсы и привязываем:
Всё, теперь у нас можно настраивать увеличение при старте программы (или вообще когда угодно), используя ScaleFactor
Например, можно прикрутить к нему слайдер. Вот полный пример:


namespace Example { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); }
public double ScaleFactor { get { return (double)GetValue(ScaleFactorProperty); } set { SetValue(ScaleFactorProperty, value); } }
public static readonly DependencyProperty ScaleFactorProperty = DependencyProperty.Register( "ScaleFactor", typeof(double), typeof(MainWindow), new PropertyMetadata(1.0)); } }

namespace Example { class RestGridLengthConverter : IValueConverter { public object Convert(object value, Type tt, object parameter, CultureInfo ci) { return new GridLength((double)value - 1, GridUnitType.Star); }
public object ConvertBack(object value, Type tt, object parameter, CultureInfo ci) { throw new NotImplementedException(); } } }
Результат:

Как настроить функцию передвижения кружочка?

Есть функция которая отвечает за перемещение, кружочка по тач-событиям. Но проблема в том, что курсор то обгоняет сам кружочек то отстает.
Как сделать так, чтоб кружочек двигался равномерно, вслед за пальцем при этом не обгонял и не отставал ?
Сам код :
var target; $('.circle').on("touchstart", function() { target = $(this); }); var moove = function (obj, x, y){ $(obj).css({"left" : x }); $(obj).css({"top" : y }); } $(window).on("touchmove", function(e) { moove($(target), event.targetTouches[0].screenX, event.targetTouches[0].screenY ); }); .circle { width: 50px; height: 50px; border-radius: 100%; background: green; position: absolute; }


фидл: https://jsfiddle.net/dxnxpybe/21/


Ответ

А Вы пробовали изменить screenX и screenY на clientX clientY, вроде как кружочек следует за пальцем.
var target;
$('.circle').on("touchstart", function() { target = $(this); });
var moove = function (obj, x, y){ $(obj).css({"left" : x }); $(obj).css({"top" : y }); }
$(window).on("touchmove", function(e) { moove($(target), event.targetTouches[0].clientX, event.targetTouches[0].clientY ); });
https://jsfiddle.net/appcscme/1/

Неявный импорт в python

Не могу разобраться в системе импортов. Почему когда я делаю:
import os.path
то мне доступен os.walk, который находится в os, хотя я явно не импортирую os? Почему-то со своими package такой финт не прокатывает. За счет чего это происходит?
upd
Я понимаю, что импорт вносит импортируемое в пространство имен модуля. поэтому определив модуль 'myutils.py' c
import requests
в другом модуле получается следущая картина
import myutils resp=myutils.requests.get('http://ya.ru') # работает resp2=requests.get('http://ya.ru') # NameError: name 'requests' is not defined
Есть какая то особенность в механизме import os в os.path? Я понимаю, что os.path есть часть os, а не 2 абсолютно отдельных package, но хочу точно понять механизм.


Ответ

Импорт в Питоне объединяет две операции
найти (загрузить и проинициализировать) модуль ввести новые имена в текущем окружении (как операция присваивания =)
На этапе поиска (пункт №1)—из спецификации import-конструкции
This name will be used in various phases of the import search, and it may be the dotted path to a submodule, e.g. foo.bar.baz. In this case, Python first tries to import foo, then foo.bar, and finally foo.bar.baz. If any of the intermediate imports fail, an ImportError is raised.
то есть import a.b.c импортирует модули a, a.b, a.b.c и более вложенный модуль не может быть импортирован успешно, если импорт неудачен для любого модуля выше.
На этапе присвоения имён (пункт №2)
If the module being imported is not a top level module, then the name of the top level package that contains the module is bound in the local namespace as a reference to the top level package. The imported module must be accessed using its full qualified name rather than directly
import a.b.c в Питоне делает доступным a имя в текущем пространстве имён (например, в глобальном пространстве имён модуля, который импортирует a.b.c) и присваивает атрибут: a.b и атрибут атрибута: a.b.c соответствующим загруженным модулям (аналог: a = sys.modules['a']; a.b = sys.modules['a.b']; ..).
Хотя вопрос с подводхом, потому что os не является Питон-пакетом (__path__ атрибут не установлен) и os.path является обычным атрибутом (таким же как os.walk) с той разницей, что os.path является модулем и os.py содержит хак: sys.modules['os.path'] = path (что разрешает import os.path конструкцию). import os сам по себе уже делает os.path доступным без import os.path

Перефразируя вопрос, используя более регулярный пример:
Почему когда я делаю: import os.pathimport html.parser то мне доступен os.walk html.escape, который находится в oshtml, хотя я явно не импортирую os html?
import html.parser импортирует как html так и (естественно) html.parser модули и так как html/__init__.py (выполняемый на этапе импорта html) определяет escape функцию, то html.escape() также доступна как если бы мы просто выполнили import html
Почему-то со своими package такой финт не прокатывает. За счет чего это происходит?
Если module.name после import module не работает, то это значит что ваш module/__init__.py не определяет name.
В сторону: работоспособность module.name не зависит от __all__. __all__ документирует какие имена являются публичными (формально имена доступные по from module import *), чтобы не добавлять к каждому имени, которое не является частью интерфейса, _ в начале (имена типа _name по умолчанию исключены из from module import *). Но это не запрещает явное обращение такое как module._name (этого следует избегать, но если очень хочется, то можно). В сторону: не используйте from module import * вне REPL или вне __init__.py файла (пример оправданного использования: asyncio/__init__.py—asyncio предоставляет "плоский" публичный интерфейс (имена доступны прямо как asyncio.name), не смотря на то что реализация распределена по многочисленным вложенным модулям).

Фиксированная нижняя граница при увеличении высоты блока

На странице в самом низу есть блок. При клике на него его высота увеличивается. Но прокрутка страницы остается на месте, а блок увеличивается вниз.


Примерно так: https://jsfiddle.net/b6wd5s4m/
Как сделать так, чтобы при раскрытии блока его нижняя граница была зафиксирована и оставалась у нижней границы экрана, а страница как бы прокручивалась вниз?


Ответ

Тогда так, доки - https://learn.javascript.ru/coordinates - https://learn.javascript.ru/metrics-window
var open_block = document.getElementById('open_block'); open_block.addEventListener('click', function() { open_block.classList.toggle('open_block'); var bot = open_block.getBoundingClientRect().bottom; window.scrollTo(0, bot); }); .block { margin-top: 300px; width: 100%; height: 100px; background-color: #04a513; transparent: 1s; } .open_block { height: 300px; transparent: 1s; }


Вопрос о создании Интерфейса для программ

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


Ответ

Хочу вначале уточнить, что задача распадается на две части. Первая - это непосредственно Ваша программа на C++, которая будет что-то делать и взаимодействовать с пользователем через HTML интерфейс. Для решения этой части есть билиотеки, например WT (см. ниже).
Вторая часть - это это рендеринг кода HTML в красивые кнопочки, закладочки, картинки, "галочки" и другие элементы интерфейса. Это очень серьезная и объемная задача. Ей занимается целая индустрия создания браузеров. В Вашем случае подойдет либо стандартный браузер в системе пользователя, который будет направлен на локальный адрес. Либо модуль готового движка типа Gecko, или Web-kit. В любом случае выбор за вами.
Библиотека WT. Ключевые возможности:
Поддержка основных браузеров (Firefox/Gecko, Internet Explorer, Safari, Chrome, Konqueror и Opera), а также браузеров простого HTML (Links, Lynx). Разработка и развёртывание на Unix/GNU Linux или Microsoft Windows (Visual Studio). Идентичное поведение как при поддержке JavaScript или Ajax, так и без таковой, насколько это возможно, посредством постепенной деградации (graceful degradation) или прогрессивного расширения (progressive enhancement). Интегрированная поддержка Юникода и локализации. Эффективный рендеринг и низкая латентность. Поддержка перемещения с помощью истории браузера (кнопки "назад"/"вперёд" и закладки), лаконичные URL при доступности истории HTML5, оптимизация для поисковиков и однообразное поведение сессий простого HTML или Ajax. Настраиваемые опции отслеживания сессий, либо посредством перезаписи URL, либо с помощью использования кук. и еще много всего "вкусного"...
Подробности на сайте (на русском)

PHP&HTML: подстановка введённых значений в поля при неудачной отправке формы

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


"/>

Т. е. мы подставляем в поля значения массива $_POST, если таковые имеются.
Но у меня почему-то не работает, т. е. не происходит подстановки в поля. Скрипт request.php при запрете отправки всвязи с ошибками ввода возвращает на страницу с формой (его работа уже отлажена).
В чем может быть причина?


Ответ

Т.к. у вас запрос (action="request.php") идёт на другой файл, вижу несколько способов:
Яваскрипт (как я понял вам не подходит); Производить обработку в том же файле, откуда отправляете форму; Использовать куки (но их опять же, можно отключить); Использовать сессии.

Иконки классов в Android Studio


Скачал проект с bitbucket, открыл в AndroidStudio. Что означают такие иконки классов? Проект запускается нормально, никаких ошибок не выдает.


Ответ

Я разобрался в проблеме. Я использовал Material Theme UI, и видно с последним обновлением студии этот плагин стал работать некорректно. Я перешел на стандартную тему и все иконки стали нормальными, стали отображаться и классы и интерфейсы.

Передать в метод, нужный компонент вектора.

В коде много вот такого, причем когда обрабатывается одна ось - не обязательно должна обрабатыватся другая.
AxisX = ((currentTouchPos.x - startTouchPos.x) / workZoneInPixX); AxisY = ((currentTouchPos.y - startTouchPos.y) / workZoneInPixY);
Отличаются только оси и чуть чуть название переменных. Как передать это в метод, чтобы обрабатывать все похожие запросы этим? Чтобы сократить и избежать дублирования кода Вижу это как то примерно вот так
float FormatXY(x_or_y) Axis = ((currentTouchPos.x_or_y - startTouchPos.x_or_y) / workZoneInPixX_or_Y); return Axis;
Но понятно, что таким образом я просто передам значения x или y, а мне бы передать именно параметр x компонент вектора или y компонент вектора, и как то подставить это в методе.
Чтобы в результате, код
AxisX = FormatXY(X)
Был эквивалентен коду
AxisX = ((currentTouchPos.x - startTouchPos.x) / workZoneInPixX);
А код
AxisX = FormatXY(Y)
Был эквивалентен коду
AxisY = ((currentTouchPos.y - startTouchPos.y) / workZoneInPixY);


Ответ

На беглый взгляд серебренной пули тут не найдешь. Думаю лучше написать две функции, типа CurrentTouchX() и CurrentTouchY() - куда запихать соответствующие выражения. Код сразу станет почище. Не думаю, что стоит городить что-то большее, ну может кто и придумает решение поинтереснее.

Ввод/вывод в консоли, C++

Здравствуйте.
Решил написать небольшую RPG-игру с псевдографикой в консоли. Для считывания нажатий клавиш использовал функцию GetAsyncKeyState из Windows.h
bool isKeyPressed(int virtualKeyCode) { short keyState = GetAsyncKeyState(virtualKeyCode); return ((keyState & 0x8000) > 0); }
В функции Update проверяю состояние клавиш и изменяю направления движения героя.
void Update() { if(_kbhit()) { if (isKeyPressed('W')) { unitsArr[heroIndex].changeMoveDirectionTo(0, -1); moveUnitTo(&unitsArr[heroIndex]); } else if (isKeyPressed('S')) { unitsArr[heroIndex].changeMoveDirectionTo(0, 1); moveUnitTo(&unitsArr[heroIndex]);
} else if (isKeyPressed('A')) { unitsArr[heroIndex].changeMoveDirectionTo(-1, 0); moveUnitTo(&unitsArr[heroIndex]);
} else if (isKeyPressed('D')) { unitsArr[heroIndex].changeMoveDirectionTo(1, 0); moveUnitTo(&unitsArr[heroIndex]); } ... }
После этого захотел написать функцию, которая выводила бы на экран вопрос, и при помощи _getch() считывала бы ответ игрока (y/n)
bool getAnswerFromLogPanel(const string questionMessage) { UpdateLog(questionMessage + " [Y]/[N]");
const char inputAnswer = tolower(_getch()); if (inputAnswer == 'y') { UpdateLog("[Y]"); return true; }
UpdateLog("[N]"); return false; }
Здесь столкнулся с проблемой, что _getch() не останавливает поток и не ждет нажатия клавиши.
При этом если использовать вместо _getch() функцию getchar() или cin.get() на экран консоли выводятся символы ранее нажатых клавиш.


Как я понял,_getch() просто считывает один символ из последних нажатых клавиш (те, которые выводит на экран getchar() или cin.get()) и поэтому не останавливает поток.
То что мне не помогло:
cin.ignore(), cin.clear(), cin.sync(), system("cls"), fflush(stdin)
То что работает, но не так как надо:
Работает, но если до этого когда-то была нажата клавиша Y или N - ответ будет считываться с нее.
do { char input = _getch(); input = tolower(input);
if (input == 'y') { UpdateLog("[Y]"); return true; }
if(input == 'n') { UpdateLog("[N]"); return false; } } while (true); При каждом срабатывании _kbhit() считывать при помощи _getch() символ с потока. Но тогда движение героя и реакция на нажатия клавиш значительно замедляется.
C++, Visual Studio 2015


Ответ

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

Angular 2 thinking and way

Ситуация: Есть два очень похожих компонента: превью статьи на главной странице, и сама статья, при переходе на "читать дальше". У компонента превью свой сервис, который тянет данные через http. В роутере, при переходе на полноую статью (другой компонент) указан компонент статьи, непосредственно.
Вопрос: Создавать копмоненту свой собственный сервис, который будет дублировать код сервиса превьюхи, либо же использовать один компонент, просто с отдельным шаблоном целой статьи (//не нашел, как юзать несколько шаблонов в одном компоненте), либо же ваш вариант. Интересует именно правильный подход с точки зрения angular way и TS. Заранее благодарю.


Ответ

Для обоих компонентов можно сделать через один сервис

Как узнать из главного потока, что побочный поток завершился ошибкой?

Есть главный поток(1) и из него вызывается побочный поток(2)
Выглядит примерно так:
Thread second_thread = new Thread(null, new Runnable() { public void run() { throws new Exception(); } }); second_thread.start(); second_thread.join();
Как узнать из главного потока, что побочный поток завершился ошибкой?


Ответ

Классы Callable и Future как раз созданы чтобы решить эту проблему. Вопрос разрешен.

Не работает блокировка для большого количества запросов

Здравствуйте. Дело в том, что я использую сокеты. И почти в одно и то же время, допустим, в 20 часов и 0 минут, у всех пользователей скрипт отправляет запрос на сокет сервер. Отправляя этот запрос, у меня есть цель: выполнить нужное мне событие (1.1) один раз, и вернуть всем результаты. Но у меня не совсем получается.
Я делаю так: когда приходит запрос от пользователя я проверяю, был ли запрос раньше, и если не было, помечаю в базе, что запрос только что произошел. Дальше, если еще кто-то шлет запрос, то уже видно, что запрос уже произошел, и текущий клиент ждет выполнения нужного мне события (1.1). Проблема состоит в том, что иногда Node.JS не успевает выполнить запрос к базе, и за это время, пока идёт запрос, успевает "проскочить" несколько клиентов и нужно мне события (1.1) выполняется столько раз, сколько пользователей проскочило, плюс тот пользователь, что инициировал первый запрос.
Как быть? Может есть какой-то алгоритм? Уже голову сломал.


Ответ

Как вариант, можно использовать именнованые локи MySQL
SELECT GET_LOCK('lock_name', 60);
Документация

Вызов шаблонной функции через Qtconcurrent::run

Есть шаблонная функция:
template auto exceptionWrapper (Object *obj, Function&& function, Args&& ...args)-> decltype((obj->*function)(std::forward(args)...)) { try { QScopedPointer tempObj(new Object(obj->getSomeData())); return (tempObj->*function)(std::forward(args)...); } catch(std::exception& e) { ... } }
Есть другая функция, которая ее вызывает через qtConcurrent::run
template void Object::callAsync(Object *obj,Function&& query,CallBack&& callBack, Args&& ...args) {
using ReturnValue = decltype(exceptionWrapper(obj, query, std::forward(args)...)); QFutureWatcher watcher; connect(&watcher, &QFutureWatcher ::finished, callBack); QFuture futureValue = QtConcurrent::run(exceptionWrapper, obj, query, std::forward(args)...);
watcher.setFuture(futureValue); }
При попытке вызова в коде:
Object object = new Object(); Object::callAsync(object, Object::objFcn, [](){qDebug()<<"qq";}, arg1, arg2);
Возникает ошибка:
ошибка: no matching function for call to 'run(, BOKZDatabase*&, AngleOrientData (BOKZDatabase::*&)(const QString&, const QString&, const QString&, const QString&, int), const QString&, const QString&, const QString&, const QString&, const int&)' QFuture futureValue = QtConcurrent::run(exceptionWrapper, db, query, std::forward(args)...); ^
Что я упустил?
UPD: В случае явного указания параметров шаблона ошибка о неопределенном типе функции остается:
template void Object::callAsync (Object *obj,Function&& query,CallBack&& callBack, Args&& ...args) {
using ReturnValue = decltype(exceptionWrapper(obj, query, args...)); QFutureWatcher watcher; connect(&watcher, &QFutureWatcher ::finished, callBack); QFuture futureValue = QtConcurrent::run(exceptionWrapper , obj, std::forward(query), std::forward(args)...); watcher.setFuture(futureValue); }
UPD 2. Минимальный пример:
class Object { public: int sum(int a, int b) { return a+b; } };
template auto fcn (Object *object, Function&& function, Args&& ...args)-> decltype ((object->*function)(std::forward(args)...)) { return (object->*function)(std::forward(args)...); }
template void callAsync(Object *object,Function&& function, Args&& ...args) {
QtConcurrent::run(fcn >, object, function, std::forward(args)...);
}
int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Object* obj = new Object();
callAsync(obj, Object::sum, 5, 6); return a.exec(); }


Ответ

exceptionWrapper сам по себе не является функцией, но неким шаблоном функции, поэтому мы не можем никуда его передать — мы можем передавать лишь что-то конкретное, а не абстракцию, коей является шаблон.
Таким образом, нам нужно конкретизировать (инстанциировать) exceptionWrapper прежде чем передавать его в QtConcurrent::run. Здесь встаёт другая проблема: с какими аргументами инстанциировать? Т.к. exceptionWrapper использует пробрасывающую ссылку (forwarding reference), идёт расчёт на то, что аргументы будут выводиться при вызове функции, но у нас ситуация иная — мы явно задаём аргументы шаблона. Конечно, мы всё равно получаем нужный результат таким вызовом:
QtConcurrent::run(exceptionWrapper, obj, std::forward(query), std::forward(args)...);
Происходит это из-за того, что у нас в callAsync пробрасывающая ссылка, а в exceptionWrapper, в результате явной инстанциации, у нас rvalue-ссылка, и применяя правила C++ по свертке ссылок мы на выходе имеем то, что и ожидали: будет инстанциирована правильная, т.е. ожидаемая нами функция exceptionWrapper. К примеру, если мы рассмотрим минимальный пример, из Вашего дополненного вопроса, то при таком вызове:
int var = 5; callAsync(obj, &Object::sum, 7, var);
Будет сгенерирована функция exceptionWrapper с такой сигнатурой: int (Object *,int (Object::* )(int,int),int &&,int &) — как раз то, что и ожидалось. Но в этом кроется другая проблема. Мы работаем с конкурентной средой и пытаемся вызвать метод Qt, который потенциально выполнит наш метод в другом потоке. Но, чтобы выполнить метод в другом потоке, он вынужден скопировать (либо же переместить, если умеет) аргументы и сохранить их до того времени, когда можно будет вызвать нашу функцию.
Сохраняя наши аргументы, Qt отбрасывает их изначальный тип и впоследствии, при передаче их в нашу функцию, все наши аргументы станут lvalue. Но в сигнатуре нашей функции есть int&&, который является rvalue-ссылкой и lvalue не может быть передано туда! Поэтому, нам придётся отказаться от пробрасывающих ссылок в exceptionWrapper — они там не нужны и только мешают, там нужен обычный const &
В результате получим такое решение:
template auto fcn(Object *object, Function function, const Args& ...args) { return (object->*function)(args...); }
template void callAsync(Object *object, Function&& function, Args&& ...args) { QtConcurrent::run(fcn, object, function, std::forward(args)...); }
Конечно, можно подумать и над альтернативными решениями, но этот ответ уже и так довольно длинный получился.

Нужна критика по архитектуре классов в С++ для реализации таблиц ModBus

Изучаю С++ и пишу библиотеку ModBus. Прошу полезного совета у Гуру по изменению архитектуры в целом или ответить на конкретные вопросы в конце.
Я хочу с помощью шаблонов классов автоматически помещать любые пользовательские данные в нужные таблицы данных ModBus с возвращением указателей на них.
class AlarmData_b01 { bool isAlarm; bool isCountActivate; };
class MeintenanceData_b01 { bool isMeintenance; bool isCountActivate; };
class MeintenanceData_f32 { unsigned short Id; unsigned long Time; float Rate; };
AlarmData_b01 *AlarmData_b01_Alarm1_ptr = InputBits::Add(); AlarmData_b01 *AlarmData_b01_Alarm2_ptr = InputBits::Add();
MeintenanceData_b01 *AlarmData_b01_Meintenance1_ptr = InputBits::Add(); MeintenanceData_b01 *AlarmData_b01_Meintenance2_ptr = InputBits::Add();
MeintenanceData_f32 *AlarmData_f32_Meintenance1_ptr = InputRegs::Add(); MeintenanceData_f32 *AlarmData_f32_Meintenance2_ptr = InputRegs::Add();
Таким образом, для класса AlarmData создается свой класс, регистрирующий все объекты типа AlarmData. Тоже происходит и для класса MeintenanceData. Дискретные данные для аварий помещаются в таблицу дискретных данных, а данные 16 бит помещаются в таблицу регистров модбас.
Так же с помощью статического метода шаблонного класса можно задать адрес для созданной области объектов в таблице ModBus.
InputBits::AddresSet(100); InputBits::AddresSet(110);
InputRegs::AddresSet(100);
Таким образом будут формироваться таблицы данных, доступ к которым будет осуществляться из вне сторонним устройством по интерфейсу RS485 и протоколу ModBus с заданием адреса внутри посылки, указанного в моей программе с помощью AddresSet.
В начале мной был создан базовый шаблон класса
template class ModBusTables { protected:
static unsigned short Addres; static unsigned short AreaSize; T_DataType *AreaData_ptr;
ModBusTables();
public:
static void AddresSet(unsigned short ModBusAddres); };
где
static unsigned short Addres - Адрес области в таблице протокола Модбас static unsigned short AreaSize - Размер объектов в области T_DataType *AreaData_ptr - Тип для приведения указателя.
Так как в ModBus фактически существует только два типа данных: дискретные и ячейки по 16 бит, то в параметрах данного шаблона будет либо bool либо unsigned short. Таким образом AreaData_ptr - это указатель на тип данных конкретной таблицы ModBus, чтобы можно было путешествовать по любым данным пользователя с помощью единого указателя.
Теперь приведу код шаблонного класса, который наследуется от одного из классов выше и расскажу в чем заключается вопрос.
template class ModBusTable;
template class TT_Table> class ModBusTable > : public TT_Table { private:
T_DataStruct AreaData;
public:
static T_DataStruct *Add() { ModBusTable *ModBusArea_ptr = new ModBusTable();
T_DataStruct *Instance_Ptr = &ModBusArea_ptr->AreaData;
ModBusTable >::AreaSize = sizeof(ModBusArea_ptr->AreaData); ModBusArea_ptr->AreaData_ptr = (T_DataType *)Instance_Ptr;
return Instance_Ptr; } };
Главная задача данного шаблонного класса - создать свой объект в статическом методе, зарегистрировать его в классе и возвратить указатель на данные пользовательского типа, а так же преобразовать этот указатель в указатель AreaData_ptr объявленный в родительском классе, чтобы с любыми пользовательскими типами можно было работать через указатель на bool или unsigned short.
Теперь сам вопрос. Для того, чтобы не вбивать много параметров в шаблон для регистрирования пользовательских данных в конкретной таблице ModBus, я применил наследование.
template class InputBits: public ModBusTable > {}; template class InputRegs: public ModBusTable > {}; template class OutputBits: public ModBusTable > {}; template class OutputRegs: public ModBusTable > {};
Как логически объединить объекты классов
InputBits и InputBits?
Объекты этих классов логически должны находится в одной таблице ModBus.
Существует ли способ заменить наследование в данном случае на что-то похожее на alias template в С++11, чтобы создавать шаблон класса с новым именем InputBits по шаблону ModBusTable? Так, чтобы работало выражение
InputBits::Add()
Приму любые советы по изменению архитектуры реализации данной задачи. Большое спасибо за прочтение, внимание и ответы!


Ответ

Для стандарта C++11 и новее можно было бы записать
template struct Base{};
template using WrapperFirst = Base;
template using WrapperSecond = Base;
int main() { WrapperFirst a; WrapperSecond b;
return 0; }
Полного аналога alias template в C++03 построить не получится.
Можно использовать шаблон структуры для частичного задания параметров базового шаблона.
template struct Base{};
template struct Wrapper { typedef Base first; typedef Base second; };
int main() { Wrapper::first a; Wrapper::second b;
return 0; }

Html. Нарисовать линию

Нужно нарисовать или любым иным способом провести линию от одного блока div к другому. Т.е. два элемента связать линией. Элементы генерируются динамически.
Строится все это дело на основе уровней. Например, есть пользователь с уровнем 1. Он будет на самом верху. Дальше пользователи с уровнем 2, они ниже. Нужно их соединить любым способом, как на схеме. Схематичный пример:


Ответ

Например так:
var first = document.getElementById('first'); var second = document.getElementById('second'); var line = document.getElementById('line').getElementsByTagName('line')[0]; function shuffle() { var pos = { ft: Math.round(Math.random() * 50), fl: Math.round(Math.random() * 50), st: Math.round(Math.random() * 100) + 100, sl: Math.round(Math.random() * 100) + 200 } first.style.top = pos.ft + 'px'; first.style.left = pos.fl + 'px'; second.style.top = pos.st + 'px'; second.style.left = pos.sl + 'px'; line.setAttribute('x1', pos.fl + first.offsetWidth); line.setAttribute('y1', pos.ft + first.offsetHeight); line.setAttribute('x2', pos.sl); line.setAttribute('y2', pos.st); } shuffle(); document.getElementById('shuffle').addEventListener('click', shuffle); div { position: absolute; border: 2px solid #000; width: 100px; height: 50px; } #line { position: absolute; top: 0; left: 0; width: 100%; height: 100%; stroke: #F00; stroke-width: 2px; z-index: -1; } #shuffle { position: absolute; top: 20px; left: 50%; }


Как запретить ввод переменной меньше/больше заданного интервала?

Как запретить ввод переменной меньше/больше заданного интервала? Например: Из динамического одмерного массива нужно удалить N элементов, начиная с номера K. Ввод размера массива, n элементов и k вводится с клавиатуры. Нужно чтобы n было не меньше и не больше size.
Подскажите только, где об этом прочитать или кусочек кода, пожалуйста.


Ответ

Возможная последовательность действий такая:
Пользователь вводит число num Проверяем число if (num ... Если число удовлетворяет проверке идём дальше, если нет возвращаемся к шагу 1.
Код, обеспечивающий сам ввод, может быть совершенно разным и будет зависеть от того с какой системой вы работаете, в консоли или GUI, используете ли какие-то специфические библиотеки типа ncurses и т.д.

Первый опыт в node.js Можно ли не переделывая с нуля получить сносный результат?

Мой первый опыт программирования, если не считать студенческих лабораторных на Delphi(и те были очень давно).
Цель: "приложение" которое на первой странице выдает кликабельный список из имен юзеров(имена берем в mongodb), а при клике на юзера перебрасывает на другую страницу, где уже отображает(беря из базы) подробные сведения о выбранном юзере. Основательно переписал, получил вот это.
Вопросы:
Общая структура более-менее адекватна? Дорабатывать имеющееся или же переделывать с нуля? В модуле userModel я подключаюсь к базе данных. Там предусмотрена простейшая обработка ошибки в виде сообщения в консоль. Как бы мне сделать так, чтобы эта ошибка попадала в express и я мог вывести в браузере объект ошибки?
//app.js: var express = require('express'); var app = express(); var router = require('./router/router'); app.use(router); app.listen(3000, function() { console.log('Listening on port 3000!
Database on mlab.com'); }); //router.js: var express = require('express'); GetFirstPage = require('../lib/GetPages').firstPage; GetSecondPage = require('../lib/GetPages').secondPage; var router = express.Router(); router.get('/', GetFirstPage); router.get('/user?:id', GetSecondPage); router.use(express.static('public')); module.exports = router; //userModel: const mongoose = require('mongoose'); mongoose.connect(require('../credentials').mongo, function(err) { if (err) console.log('Error database connection
', err) }); const userShema = mongoose.Schema({ name: String, age: String, disciplines: String, }); module.exports = mongoose.model('User', userShema); //GetPages.js: var express = require('express'); var app = express(); var _ = require('underscore'); const User = require('./exportFromDB').user; const NamesList = require('./exportFromDB').namesList; module.exports.firstPage = function(req, res) { Promise.all([ NamesList(), readMainPage() ]).then(function(results) { const list = results[0].map(function(item) { return item.name }) res.send(results[1]({ 'list': list })) }) } module.exports.secondPage = function(req, res) { Promise.all([ User(decodeURIComponent(req.query.id)), readSecondPage() ]).then(function(results) { res.send(results[1]({ name: results[0][0].name, age: results[0][0].age, disciplines: results[0][0].disciplines })) }) } function readMainPage() { const myFile = require('../lib/exportFile').mainPage; return myFile(); } function templateMainPage(template) { res.send(template({ 'list': List })) } function readSecondPage() { const myFile = require('../lib/exportFile').secondPage; return myFile(); } //ExportDB.js userModel = require('./userModel'); module.exports.namesList = () => { return new Promise(function(resolved, rejected) { userModel.find({}, 'name -_id', function(err, data) { resolved(data) }) }) } module.exports.user = (url) => { return new Promise(function(resolved, rejected) { userModel.find({ name: url }, function(err, data) { resolved(data) }) }) }


Ответ

Как-то так стандартно выглядит запрос страницы всех юзеров:
app.get('/', function(req, res) { users.find({}, (err, docs) => { res.locals.users = docs; res.render('list'); }; };
А в шаблоне страницы списка - юзеры выводятся в цикле each user in users, где каждый обёртывается в ссылку с атрибутом такого вида href="/users/#{user._id}" (или какой-там у вас синтаксис шаблонизатора)
А запрос страниц отдельных юзеров - app.get('/users/:id', ..., и в его обработчике, в объекте запроса значением параметра req.params.id будет айдишник юзера в базе, по которому он легко и запрашивается -
app.get('/users/:id', function(req, res) { users.find({_id: req.params.id}, (err, result) => { res.locals.user = result; res.render('user'); }; };
Шаблон страницы получил объект юзера - user._id user.name user.age и т.д. Всего и делов - спасибо ТиДжею Каравайчуку (или как там его) за Express.

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

Я не уверен, что мой подход правильный может есть другая идея?
Мне нужно имплементировать календарь в своем приложении с возможностью Range selection по датам.
Я для этого решил одну из самых популярных библиотек применить
https://github.com/prolificinteractive/material-calendarview
так как знаю, что Calendar View не приспособлен для Range selection
И все работает отлично пока не нужно поменять язык приложения с Английского на Иврит (так же как и Арабский слева направо)
Название месяцев меняется название дней недели тоже, но не меняется направление последовательности (оно тоже должно быть не rtl - cправа налево , а ltr - слева направо)
Вот скрин на англ

Вот как на иврите android:supportsRtl="false"

И тут тоже на иврите но android:supportsRtl="true" (не знаю почему но кроме того, что поменялось направление стрелок больше ничего)

Я нашел такой баг фикс как раз об этом
https://github.com/prolificinteractive/material-calendarview/pull/573
Это как раз то, что мне нужно, согласно этому фиксу направление должно меняться, но в моем случае видно, что это не так.
Что я делаю не так или подскажите, как можно это решить по другому?


Ответ

Вы можете использовать форк этого репозитория от того кто сделал этот коммит:
https://github.com/anasanasanas/material-calendarview
Придется использовать JitPack
В принципе, все предельно просто описано и на странице:
1 Пропишите:
allprojects { repositories { ... maven { url 'https://jitpack.io' } } }
2 Добавьте:
dependencies { ... compile 'com.github.anasanasanas:material-calendarview:1.4.4' }
Реультат:

Анимация JQuery. Как вернуть квадрат обратно?

Как при втором нажатии на кнопку вернуть квадрат обратно? Код ниже.

By default, all HTML elements have a static position, and cannot be moved. To manipulate the position, remember to first set the CSS position property of the element to relative, fixed, or absolute!



Ответ

используйте toggleclass и transition для плавности:
$("button").click(function(){ $("div").toggleClass('move_right'); }); div { left: 0px; transition: all .5s; background:#98bf21; height:100px; width:100px; position:absolute; } .move_right { left: 250px; }

By default, all HTML elements have a static position, and cannot be moved. To manipulate the position, remember to first set the CSS position property of the element to relative, fixed, or absolute!


Vue.js 2. Как можно сделать плавную анимацию используя v-for. (no JQ)

Есть страница с новостями, которая постоянно спустя 5 сек отправляет запрос на /getNews, ответ присваиваю в items. Далее через v-for происходит рендер блоков. Мне не нравиться, что они рендерятся сразу, я бы хотел какой нибудь плавности.
Код (News.vue):



Ответ

Для анимации списков надо использовать transition-group. https://vuejs.org/v2/guide/transitions.html#List-Transitions
Основные моменты:
элементы списка должны иметь уникальный ключ (задается через :key); по умолчанию элементы списка рендерятся в контейнер span, но это можно поменять использую атрибут tag;
И небольшой пример:
new Vue({ el: '#app', data() { return { items: [] } }, mounted() { setTimeout(() => { this.items = [ {id: 1, text: "Lorem ipsum"}, {id: 2, text: "Lorem ipsum"}, {id: 3, text: "Lorem ipsum"}, {id: 4, text: "Lorem ipsum"}, {id: 5, text: "Lorem ipsum"} ] }, 1000); } }) .item { height: 40px; width: 70px; border: 1px solid #ccc; margin: 5px; } .list-enter-active, .list-leave-active { transition: all 0.9s; opacity: 1; } .list-enter, .list-leave-to { opacity: 0; transform: translateX(50px) rotate(90deg); }

{{item.text}}

Максимальное количество чисел из массива, сумма которых не превосходит K

Здравствуйте. Дан массив A из N натуральных чисел. Нужно найти размер подмассива A максимальной длины, сумма элементов которого не превосходит K
Пример:
A = [1, 4, 2, 3] K = 6
Ответ: 3 (подмассив [1, 2, 3])
Правильно ли я думаю, что если отсортировать массив, то ответом будет количество первых элементов массива, сумма которых не превосходит К? И есть ли способ получше?


Ответ

Если ваша интерпретация постановки задачи действительно верна, то предложенный вам алгоритм - верен. Однако можно предложить более эффективное решение.
Вы можете применить обыкновенный алгоритм quick sort с дополнительной модификацией.
Если после выполнения partitioning оказывается, что сумма элементов в левой (меньшей) части массива не меньше чем K, то правая часть массива вас больше не интересует и тратить время на дальнейшую сортировку правой части никакого смысла нет. В случае же, когда сумма элементов в левой (меньшей) части массива меньше чем K, вы сразу знаете, что все элементы левой части заведомо входят в искомый подмассив и тратить время на дальнейшую сортировку левой части никакого смысла нет.
Это та же самая стратегия, по которой работает классический алгоритм поиска "k наименьших элементов", с той только разницей, что вы ищете не k наименьших элементов, а неизвестное число наименьших элементов, чья сумма не превосходит K
Таким образом на каждом уровне рекурсивного подразбиения вам нужно выполнять рекурсивный вызов только для одной половины подразбиения, в то время как вторая половина либо полностью игнорируется, либо просто целиком отправляется на выход (и затем игнорируется). Такой алгоритм должен легко допускать истинно циклическую реализацию, без использования стека.

Анимированное появление тени у path svg

Реализовала появление тени при наведении у path svg

#Projektablauf path { cursor: pointer; transition: all 0.3s ease; } #Projektablauf path:hover { filter: url(#dropshadow); }
Но как сделать появление тени плавным? transition: all 0.3s ease; не срабатывает.


Ответ

Можно продублировать ваши path, по умолчанию применить к ним ваш фильтр, поставить opacity:0 и отображать их при наведении на path без фильтра:
#Projektablauf path { cursor: pointer; transition: all 0.3s ease; } #Projektablauf path.hover { filter: url(#dropshadow); opacity: 0; pointer-events: none; } #Projektablauf path:hover+path.hover { opacity: 1; }
Ну, или отобраражать их при наведение на них самих:
#Projektablauf path { cursor: pointer; transition: all 0.3s ease; } #Projektablauf path.hover { filter: url(#dropshadow); opacity: 0; } #Projektablauf path.hover:hover { opacity: 1; }

Зачем в чужом коде тело конструктора вынесено в отдельный метод?

function A() { this._init.apply(this, arguments); }
A.prototype._init = function() { // ... }
let a = new A();
Не могу понять, зачем необходимо такое разделение? Зачем в теле конструктора вызывать другой метод в контексте того же объекта, если весь код, находящийся в теле конструктора можно поместить в сам конструктор? Какие преимущества дает такое разделение?
И еще. Зачем здесь вообще #apply()? Разве простой вызов this._init(arguments) не выполнит то же самое?


Ответ

Как оказалось, всё дело тут в хорошо запрятанной документации. В StyleGuide'ах обнаружилась инфа следующего вида:
Our pattern for writing classes is:
function Foo(arg1, arg2) { this._init(arg1, arg2); }
Foo.prototype = { _init: function(arg1, arg2) { this._myPrivateInstanceVariable = arg1; }, myMethod: function() {
}, myClassVariable: 42, myOtherClassVariable: 'Hello' }
Чем такое решение обусловлено, ответить не могу. А решение впихнуть сюда .apply(), как подсказал в комментариях к вопросу @Grundy обусловлено попыткой воссоздать функционал spread оператора. К слову, движок (GJS), интерпретирующий код, позволяет использовать spread. Поэтому конкретно в этом случае использование .apply() ничем не обусловлено, кроме, судя по всему, разве что незнания автора кода о существовании такого оператора.