Страницы

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

пятница, 1 марта 2019 г.

Можно ли упростить цикл, используя java 9 или java 8?

Можно ли как-то упростить этот цикл, используя java 9 или java 8?
for (String s : list) { if (s.indexOf("D") != -1) { numberList.addAll(getDoubleFromString(s)); } else { if (s.indexOf(".") != -1) { numberList.add(new TypeSatellite(BigDecimal.valueOf(Double.valueOf(s)))); } else { numberList.add(new TypeSatellite(Integer.valueOf(s))); } } }


Ответ

Давай-те сделаем оптимизации по шагам (основная сложность непонятно что принимают TypeSatellite и какой тип у numberList, поэтому напишу для object'a):
1) Можно заменить s.indexOf(...) != -1 на s.contains(...), то есть записать что-то вроде
list.forEach(s -> { if (s.contains("D")) { numberList.addAll(getDoubleFromString(s)); } else { if (s.contains(".")) { numberList.add(new TypeSatellite(BigDecimal.valueOf(Double.valueOf(s)))); } else { numberList.add(new TypeSatellite(Integer.valueOf(s))); } } });
2) Можно вынести общий код
list.forEach(s -> { if (s.contains("D")) { numberList.addAll(getDoubleFromString(s)); } else { Object number = s.contains(".") ? BigDecimal.valueOf(Double.valueOf(s)) : Integer.valueOf(s); numberList.add(new TypeSatellite(number)); } });
3) Вынесем общий функцию:
list.forEach(s -> { numberList.addAll(getListNumber(s)); }); }
private static Collection getListNumber(String s) { if (s.contains("D")) { return getDoubleFromString(s)); } else { Object number = s.contains(".") ? BigDecimal.valueOf(Double.valueOf(s)) : Integer.valueOf(s); return Collections.singleton(new TypeSatellite(number)); } }
4) последний шаг используем стрим
numberList = list.stream().flatMap(::getListNumber ).collect(Collectors.toList());
private static Stream getListNumber(String s) { if (s.contains("D")) { return getDoubleFromString(s).stream(); } else { Object number = s.contains(".") ? BigDecimal.valueOf(Double.valueOf(s)) : Integer.valueOf(s); return Stream.of(new TypeSatellite(number)); } }

Node.js приложение запустить на хостинге

Всем привет! У меня проблемка. Перерыл google и satackoverflow но не могу найти решения. Написал сайт на Node+react+mongo. Соответственно все делал на локале (Запуск сервера и коддинг). Теперь взял пробное место на хостинге Timeweb. Залил туда проект, установил на сервере Node + все зависимости проекта. Код работает если вызываю команду node app.js, который запускает этот код
const express = require('express'); const MongoClient = require('mongodb').MongoClient; // const path = require('path'); // const logger = require('morgan'); // const multer = require('multer'); const bodyParser = require('body-parser'); const db = require('./config/db'); const app = express(); const port = 8000; app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); app.use(express.static(`${__dirname}/public`)); const dirname = __dirname; MongoClient.connect(db.url, (err, database) => { if (err) return console.log(err) require('./server/routes')(app, database, dirname); app.listen(process.env.PORT || port, () => { console.log(process.env.PORT || port) }) })
и выводит в консоль соответствующий порт 8000. Вопрос собственно в том, как мне сделать чтобы мое приложение запускалось и все рендерилось под доменом так же как я это видел на локале.
Можно хотябы ссылку на какуюто информаию или туториал.
Извините а такой банальный вопрос. Всем спасибо заранее!)


Ответ

Зависит от того, что у вас там за сервер. Для nginx делать так:
Для начала сам nginx установить sudo apt-get -y install nginx Открыть конфиг файл sudo nano /etc/nginx/sites-available/default и написать там:
server { listen 80; server_name имя_вашего_домена;
location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; } } Перезапустить nginx sudo service nginx restart Остаётся только в настройках DNS вашего домена направить его на ip этого сервера.

Как использовать новые геттер и сеттер?

Помогите пожалуйста отрефакторить код. Я написал компонент, который представляет из себя форму для отправки вопросов. Так же он выводит заданные на настоящий момент вопросы (пока в консоль, но это не принципиально). Вместо базы данных для учебных целей использую localstorage.
Итак, вот мой сервис, которые работает с "базой данных":
@Injectable() export class QuestionsService {
private questions: Question[];
constructor() { this.questions = localStorage.questions ? JSON.parse(localStorage.questions) : []; }
getQuestions() { console.log('qqq'); return this.questions; };
setQuestions(question): void { this.questions.push(question); localStorage.questions = JSON.stringify(this.questions); };
}
Вот описанный тип:
export class Question { text: string; speakerId: number; dateHuman: string; dateUnix: string; }
Вот компонент:
export class QuestionComponent implements OnInit {
private questions: Question[] = [];
constructor(private questionsService: QuestionsService) { }
ngOnInit() { this.getQuestions(); console.log(this.questions); }
private sendQuestion(): void { this.questionsService.setQuestions({ "text": "42256yregd", "speakerId": 23, "dateHuman": "223 oct", "dateUnix": "22222" }); };
private getQuestions(): void { this.questionsService.getQuestions().map(question => { this.questions.push(question); }); };
}
Эта система работает. Но мне хотелось бы использовать новые модные геттеры и сеттеры из стандарта es6. Вот моя попытка:
Сервис:
private questions: Question[];
constructor() { this.questions = localStorage.questions ? JSON.parse(localStorage.questions) : []; }
get questions() { console.log('qqq'); return this.questions; };
set questions(question): void { this.questions.push(question); localStorage.questions = JSON.stringify(this.questions); };
компонент:
.... ..
private sendQuestion(): void { this.questionsService.questions = { "text": "42256yregd", "speakerId": 23, "dateHuman": "223 oct", "dateUnix": "22222" }; };
private getQuestions(): void { this.questionsService.questions().map(question => { this.questions.push(question); }); };
.... ....
Но консоль выводит ошибку:
Duplicate identifier 'questions'.


Ответ

Проблема у вас вот в чем:
private questions: Question[]; // раз
get questions() { // два set questions(question): void {
У вас объявлено два свойства с одним именем. Так нельзя делать, о чем вам и говорит tsc. Эта проблема решается добавлением префикса к приватному свойству:
private _questions: Question[];
get questions() { set questions(question): void {

typedef и пользовательский тип [дубликат]

На данный вопрос уже ответили: Зачем нужен typedef? 2 ответа В чем разница между typedef struct/class и пользовательским типом, созданным с помощью struct/class? Да, я понимаю, что typedef не создаёт новый тип, а делает всего лишь дополнительное имя для данного типа, но все таки, неужели создание типа так невыгодно? typedef:
typedef struct { int size; int * massive; } MyStr;
Тип:
struct MyStr{ int size; int * massive; };


Ответ

В Си++ разницы особой нет, разница есть в чистом Си. И в Си++ это используется, скорее, как пережиток Си. В языке Си есть 4 типа пространств имен: 1) Метки (используется в конструкциях goto) 2) Тэги (имена структур, объединений и перечислений) 3) Члены структур и объединений 4) Все остальное (имена функций, объектов, констант и все typedefы).
Так же стандарт Си требует (C11 6.2.3) раздельное пространство имен для каждой из этих категорий. Ну и все компиляторы и IDE в целом поддерживают этот стандарт. То есть, все эти элементы создаются в разных пространствах имен. Поэтому, например, такой код
struct myStruct {}; myStruct str;
не скомпилируется компилятором Си (но скомпилируется Си++), потому что тип myStruct находится в раздельном пространстве имен (не в том, в котором создается переменная str). Что бы такой код работал, str нужно объявлять так:
struct myStruct str;
Что бы не писать слово struct перед каждым объявлением переменной можно использовать прием с typedef. Т.к. все, что объявлено через typedef помещается в более общее пространство имен (в то же, где и все остальные объекты), то теперь нет необходимости писать слово struct перед каждым объявлением.

Перерисовка окна при изменении его размера

Только начал изучать DirectX и WinAPI. Написал простейшую программу: создаёт квадрат на всё окно и "раскрашивает" его шейдером. Но при уменьшении размера окна изображение сжимается, а при увеличении - растягивается. Как сделать, чтобы этого не происходило, т.е. при уменьшении, например, изображение не сжималось, а просто показывалась его меньшая область. Пробывал сделать это так:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { // ...
switch (message) { // ...
case WM_SIZE: D3D11_VIEWPORT vp; vp.Width = (FLOAT)LOWORD(lParam); vp.Height = (FLOAT)HIWORD(lParam); vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; if (g_pImmediateContext) g_pImmediateContext->RSSetViewports(1, &vp); break;
// ... }
return 0; }
Думал, сработает, но получил странное поведение: при уменьшении размера окна изображение ещё сильнее уменьшается, а при увеличении остаётся неизменным. Как реализовать описанное ранее поведение правильно?


Ответ

Вне зависимости от фактических размеров окна его DirectX-ная система координат всегда будет описывать прямоугольник (0, 0)-(1, 1) (DX10) или (-1, -1)-(1, 1) (DX9). Для этого DirectX будет специально масштабировать (а в DX9 ещё и перемещать) координаты на кадровом буфере.
Соответственно, ваша задача заключается в применении матрицы трансформации, которая отменяла бы подобный эффект, «сжимая» обе координаты прямо пропорционально габаритам окна. Причём эта матрица должна применяться после применения всех остальных матриц, если они есть.
Для DirectX 11 (упомянутого в вопросе) матрица будет иметь следующий вид:
где: α — масштабный коэффициент, указывающий, сколько пикселей должно приходиться на единичный отрезок обзорной области. w, h — ширина и высота клиентской области окна; получать при каждом WM_SIZE с помощью LOWORD(lParam) и HIWORD(lParam) соответственно.

Почему метод onEditorAction не отлавливает нажатие Enter на программной клавиатуре при включенной русской раскладке, но отлавливает его на английской?

Прочитал на этом сайте и на его английском прародителе много схожих вопросов и ответов, перепробовал разные условия if, но так и не понял, почему в английской раскладке все работает так, как я и ожидаю, тогда как в русской - нажатие enter просто переводит в новую строку (неужели код нажатия клавиши зависит от раскладки?). У EditText задан атрибут inputType="textMultiLine".
public boolean onEditorAction(TextView textView, int actionId, KeyEvent event) {
if (event != null) {
if ((event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN)) { // сохраняем текст, введенный до нажатия Enter в переменную currentMessage = editText.getText().toString(); editText.setText(""); return true; }
} return false; }
Пробовал менять KeyEvent.ACTION_DOWN на actionId == EditorInfo.IME_ACTION_SEND с предварительным editText.setImeActionLabel("SEND", EditorInfo.IME_ACTION_SEND);, но это не помогло. Заранее благодарю за ответ.


Ответ

Java
editText.setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { boolean handled = false; if (actionId == EditorInfo.IME_ACTION_SEND) {
currentMessege = editText.getText().toString(); setText(currentMessege); editText.setText("");
handled = true; } return handled; } });
XML

Вместо textMultiLine Используйте android:inputType="textImeMultiLine" - проверил лично, работает на все 100% при русской и английской раскладке.

Документация
P.S. Вкратце, "Enter" на клавиатуре - это imeOptions (Specify the Input Method Action), существуют:
IME_ACTION_SEND (картинка письмо) IME_ACTION_DONE (галочка) IME_ACTION_SEARCH (лупа)
и т.д
в Java нужно обозначать .IME_ACTION_*, в xml android:imeOptions="action*"

Использование RSA для “Ментального покера”

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


Ответ

И идентичными модули могут быть только если у обоих одинаковые пары ключей - а это лишает всю процедуру шифрования смысла.
Здесь вы неправы, для одного модуля существует очень много разных пар ключей. Обратите внимание на процедуру генерации ключей RSA: публичная экспонента e выбирается случайным образом (на практике всегда берут 65537). Мы можем выбрать любое e, и получим уникальную пару ключей.
В описанной в книге схеме не совсем тот RSA, который привычно видеть в других криптосхемах. Стороны генерируют разные ключи для одного модуля, и обе стороны знают его разложение на простые числа. Факторизация дает возможность вычислить приватный ключ с публичного ключа, но в приведенной схеме они не знают даже публичные ключи друг друга.
Только на шаге 7 они раскрывают свои ключи, что бы убедится в отсутствии мошенничества.

Как изменить размер Callback кнопок в Telegram bot?

Я пишу телеграмм бота на C#, использую библиотеку Telegram.Bot. Когда на Callback кнопке очень много текста он не помещается на нее и телеграмм автоматически дописывает "...".
Есть ли способ изменить размер кнопки, чтобы весь текст помещался на нее или сделать так, чтобы текст автоматически прокручивался по кнопке?
if(ev.CallbackQuery.Data == "callback1") { var keyboard = new Telegram.Bot.Types.ReplyMarkups.InlineKeyboardMarkup( new Telegram.Bot.Types.InlineKeyboardButton[][] { new [] { // First column new Telegram.Bot.Types.InlineKeyboardButton("Button text","callback2"), }, new [] { new Telegram.Bot.Types.InlineKeyboardButton( "Thi is exampl. example example example.A lot of text that does not fit on the button","callback3"), }, } ); await Bot.SendTextMessageAsync(message.Chat.Id, "Message text", false, false, 0, keyboard, Telegram.Bot.Types.Enums.ParseMode.Default); }
Вот как это выглядит:


Ответ

Нет, в текущей версии бот апи не реализован перенос строк и тп. Да оно и логично с точки зрения UX/UI - как будут выглядеть разнокалиберные кнопки или каково будет пользователю пытаться прокрутить текст в кнопке на 4 дюймовом экране? Просто мука для эстета и перфекциониста. Бот апи не может служить абсолютной заменой мобильным приложениям по понятным причинам - возможности не те.

Выход есть, точнее - их даже два:
1. Используйте лаконичные надписи, тестируйте на разных устройствах. То, что не годится для 5 дюймов, прекрасно подходит для десктопа и наоборот
2. Если надпись невозможно уместить в требуемый размер - используйте разъясняющие сообщения. Можно предварять поясняющим сообщением непосредственно сообщение, с той самой инлайн-кнопкой, на которой, в свою очередь, за счёт того, что пояснение уже было, надпись можно выводить упрощённо. Например - поясняющее сообщение - Предлагаем Вам выбрать грибы. К съедобным грибам относятся .... К несъедобным относятся ... Далее сообщение с инлайн-кнопками - Ознакомьтесь с нашим ассортиментом Выбрать съедобные Выбрать несъедобные

Изменение модификатора доступа при переопределении

Вопрос задавался на собеседовании: "Возможно ли при переопределении метода изменить модификатор доступа?" При ответе, что изменить можно, но при условии его расширения (package private -> protected -> public) прозвучал встречный вопрос: "А почему так?" ??? Понятно, что если нарушить это условие, то будет ошибка на стадии компиляции. Возможно чтобы ответить на этот вопрос нужны более глубокие познания в ООП? Если у кого есть соображения...


Ответ

Принцип подстановки Лисков
Там, где допустимо использовать тип Х, должно быть допустимо использовать и любой тип, наследующийся от него.
Если гипотетически предположить, что вам всё-таки удастся это нарушить, то получится, что в коде, который требует значение некоего базового типа (и использует у него тот метод, который вы перекрыли более ограниченным) не всякий более конкретный тип можно использовать.
Наследование получается неполным, и выходит, что система типов перестаёт контролировать, что наследующие типы применимы в коде для базового.

Русскоязычный вариант для термина slug

Как корректно на русский переводится термин 'slug'?
Контекст употребления можно найти в этих вопросах:
Создание ЧПУ для категорий сайта с помощью PHP .html как часть slug Обновление slug в django Как передать slug в urls.py
Судя по всему это что-то имеющее отношение к ЧПУ (человекопонятный url), но что именно?


Ответ

Технически обычно это уникальный человекочитаемый ключ для поиска, который может не только идентифицировать единственную запись, но и быть осмысленным для пользователей при прямом прочтении. В конкретных случаях бывают и другие требования, вроде безопасности для вставки в URL (не всякие символы разрешены), определённой максимальной длины или чувствительности к регистру.
Почему именно так? Потому что термин в основном употребяется в отношении замены "непонятного id" на "понятный slug" в соответствующих технических статьях, руководствах и документации к связанным библиотекам (например: friendly_id, eloquent-sluggable). Потому что при генерации этих slug'ов возникает несколько стандартных задач:
спасти читаемость при фильтрации символов (например, что делать с кириллицей: вырезать? транслитерировать? экранировать в %XX-формат? не трогать?) обеспечить уникальность, когда возможны дублирующиеся описания на человеческом языке (что ограничивать обычно вредно)
Известный устоявшийся перевод, кроме англицизма "слаг", мне неизвестен, и, возможно, не существует вовсе.

Но бывает и иначе. Реже случается, что их уникальностью пренебрегают.
То, что используется здесь, на Stack Exchange:
/{сущности}/{id}/{название} ^^^^^^^^^^ вот это
...по приведённому определению slug'ом не является, поскольку не участвует в поиске записи, поиск происходит только по id, а на месте сегмента {название} реально может быть любой мусор
Хотя если при обсуждении кто-то назовёт последний сегмент slug'ом, я пойму, что он имеет в виду идентификатор для человека (необязательно уникальный технически).
Получается, вот ещё одно определение, которым пользуются на практике. А значит, термин не является однозначным.

Я мог бы предложить несколько вариантов перевода, возможно даже в процессе обсуждения здесь на чём-то остановимся, но донести это до широкой общественности видится мне задачей практически невыполнимой.

Вложенные транзакции SQL сервер

Здравствуйте.
Ситуация следующая. Есть SQL Server 2008, в программе используется драйвер QODBC3. Соединение установлено, данные пишутся/читаются.
Проблема, видимо, в отсутствии понимания принципа работы с вложенными транзакциями. Судя по документации к восьмому серверу, каждый новый BEGIN TRANSACTION увеличивает счётчик TRANCOUNT на единицу. Каждый COMMIT уменьшает его на 1. Транзакция завершается и фиксируются изменения, когда счётчик станет равен 0. У меня же выходит, что первый же commit завершает транзакцию вне зависимости от того, сколько было BEGIN TRANSACTION. Пусть имеется база и запрос к ней:
db = QSqlDatabase::addDatabase("QODBC3"); ... query = new QSqlQuery(db); ...
Выполняем:
db.transaction(); query->exec("INSERT INTO TestOnly (Value) VALUES('1')"); db.transaction(); query->exec("INSERT INTO TestOnly (Value) VALUES('2')"); db.commit(); query->exec("INSERT INTO TestOnly (Value) VALUES('3')"); db.rollback();
В результате в таблице оказываются все 3 значения ('1','2','3'). И в SQL SMS видно, что после первого же коммита пропадает единственная активная транзакция. Соответвственно последующий RollBack ничего не делает.
В чём здесь проблема? Я совсем не правильно понял идею со счётчиком открытых транзакций, или просто драйвер/Qt не поддерживают такой функционал? Или я упустил что-то где-то в настройках (сервера/драйвера)?

С проверкой возвращаемых значений операций открытия/закрытия транзакций пример выглядит страшнее, но ничего не поделать:
bool ok;
ok = db.transaction(); qDebug() << "Start transaction" << " result = " << ok << "; errorText: " << db.lastError().text(); PrintTranCount(); //0
query->exec("INSERT INTO TestOnly (Value) VALUES('1')"); PrintTranCount(); //1
ok = db.transaction(); qDebug() << "Start transaction" << " result = " << ok << "; errorText: " << db.lastError().text(); PrintTranCount(); //2
query->exec("INSERT INTO TestOnly (Value) VALUES('2')"); PrintTranCount(); //3
ok = db.commit(); qDebug() << "Commit transaction" << " result = " << ok << "; errorText: " << db.lastError().text(); PrintTranCount(); //4
query->exec("INSERT INTO TestOnly (Value) VALUES('3')"); PrintTranCount(); //5
ok = db.rollback(); qDebug() << "Rollback transaction" << " result = " << ok << "; errorText: " << db.lastError().text(); PrintTranCount(); //6
Результат:
Start transaction result = true ; errorText: " " Transaction Count 0: 0 Transaction Count 1: 1 Start transaction result = true ; errorText: " " Transaction Count 2: 1 Transaction Count 3: 1 Commit transaction result = true ; errorText: " " Transaction Count 4: 0 Transaction Count 5: 0 Rollback transaction result = true ; errorText: " " Transaction Count 6: 0
Иными словами, вторая db.transaction() не инкриминирует счётчик совсем и транзакция полностью завершается после первого COMMIT'а. Буду благодарен за любые подсказки по этому поводу.
Вывод значения счётчика транзакций:
void PrintTranCount() { static int Num = 0; query->exec("SELECT @@TRANCOUNT");query->first(); qDebug() << "Transaction Count "<< Num << ": " <value(0).toInt(); Num++; }


Ответ

Краткий ответ
Вызов метода QSqlDatabase::transaction() не начинает транзакцию в базе, а лишь включает режим "ручной режим фиксации". Для того чтобы начать явную транзакцию, нужно отослать базе непосредственно команду "begin tran".
Пояснения
Проблема заключалась в том, что я принимал желаемое поведение драйвера за действительное и поленился залезть в исходники. Спасибо @teran за то, что "ткнул носом" куда надо.
Описание функции bool QSqlDatabase::transaction() гласит:
Begins a transaction on the database if the driver supports transactions. Returns true if the operation succeeded. Otherwise it returns false.
Из этого описания я сделал ложный вывод о том, что драйвер отправляет базе команду открытия транзакции, что, мягко говоря, не соотносится с действительностью.
Из исходников:
bool QSqlDatabase::transaction() { if (!d->driver->hasFeature(QSqlDriver::Transactions)) return false; return d->driver->beginTransaction(); }
Функция "спрашивает" драйвер о поддержке транзакций, вызывая hasFeature(QSqlDriver::Transactions). Если получает положительный ответ - вызывает метод драйвера beginTransaction().
bool QODBCDriver::beginTransaction() { Q_D(QODBCDriver); //---------------Проверяем открыта ли база----------------- if (!isOpen()) { qWarning("QODBCDriver::beginTransaction: Database not open"); return false; } //------Инициализация переменной-параметра значением,----- //------отключающим автоматический commit операций-------- SQLUINTEGER ac(SQL_AUTOCOMMIT_OFF); //-------Устанавливаем этот параметр и проверяем на ошибки----------------- SQLRETURN r = SQLSetConnectAttr(d->hDbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)size_t(ac), sizeof(ac)); if (r != SQL_SUCCESS) { setLastError(qMakeError(tr("Unable to disable autocommit"), QSqlError::TransactionError, d)); return false; } return true; }
В функции beginTransaction(), в свою очередь, единственное производимое действие - отключение автоматического подтверждения изменений в базе. Никаких "begin tran".
В результате, с отключённым автокоммитом база данных при выполнении каждой инструкции начинает неявную транзакцию. Это (а не сама функция transaction(), как я думал) и приводит к установке счётчика транзакций @TRANCOUNT в единицу. Нет никакой вложенности транзакций в данном случае, она одна и завершается сразу после первого же COMMIT'а.
Функция commit() (как и rollback()) содержит в себе вызов QODBCDriver::endTrans(), который вновь отключает режим неявных транзакций. Это отключение объясняет, почему в моём примере в результирующей таблице была и третья строка (та, что перед ROLLBACK'ом). COMMIT перед отправкой команды вставки этой строки завершил неявную транзакцию и отключил ручной режим фиксации, так что INSERT был автоматически зафиксирован в базе, а rollback() отработал вхолостую.

Программа не видит путь к файлу C:\Windows\ System32\nslookup.exe

Программа не видит путь к файлу C:\Windows\System32
slookup.exe Проверка естественно всегда выдает "Путь не найден". То же самое происходит и например с путем к фалу notepad.exe в этой же папке, но при этом если обратиться к файлу C:\Windows\twin_32.dll то программа его находит. Подскажите куда копать? Нужно назначить текущего пользователя владельцем папки System32?
if (File.Exists(@"C:\Windows\System32
slookup.exe")) { Console.WriteLine("Путь найден"); } else Console.WriteLine("Путь не найден");


Ответ

Дело в File System Redirector'е (https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187(v=vs.85).aspx)
Если кратко, %windir%\System32 - для 64-битных приложений. 32-битные приложения система перенаправляет в %windir%\SysWOW64 где вашего файла вполне может и не быть.

Импорт данных секвенирования и обработка SAM-файлов в TDictionary

До сих пор, работая непосредственно с SAM-файлами, мы использовали массивы. Сейчас хотим перейти на TDictionary, поскольку он гораздо удобнее в плане поиска. Возникают вопросы: 1. Иерархия словаря. Как я вижу себе структуру, которая была бы удобна для поиска:
type DataType = record name,qual, info, seq:string; data:array[1..30] of double; paired, structured:boolean; ref:integer; end;
TData3 = TDictionary; // по имени референса TData2 = TDictionary; // по позиции внутри хромосомы TData1 = TDictionary; по хромосомам
var dd: TData1;
тогда я могу достаточно быстро пробежаться вниз по дереву chr->pos->ref и все записи будут уникальны. А для работы с переменной dd создаю свой класс, где будут все рутины. Прав ли я, предполагая такую структуру?
Как правило, в большинстве биоинформатических утилит для обозначения хромосом используются строковый тип ['1'...'22','X','Y','MT']. Формально, я могу TData1 определить как
type TData1 = TDictionary ; по хромосомам
но боюсь, что выигрывая в удобстве, потеряю в скорости поиска. Так ли это?
Спасибо заранее за помощь!


Ответ

Вначале отвечу на второй вопрос. По опыту, разницы в скорости не наблюдается. Более того, удобнее оставлять сведения о хромосоме именно в текстовом виде, так как порой приходится иметь дело со сложными именованиями хромосом, а не все утилиты поддерживают таблицу номерного соответствия. Более того, я предлагаю совместить первый и второй уровень вашего словаря, сделав ключом сразу полную координату {chr, pos} в виде строки формируя её либо так Key:= chr + ',' + IntToStr(pos), либо так Key:= chr + #9 + IntToStr(pos). Первый случай удобен для экспорта в Excel или BED, второй - для SAM/BAM. Скорость поиска возрастёт, неудобств при формировании ключа - минимум. И ещё, отдельный класс создавать, на мой взгляд, не нужно. Наследуйте непосредственно TDictionary, так будет гораздо удобнее. Суммируя всё вышенаписанное, предлагаю сделать так:
type DataType = record name,qual, info, seq:string; data:array[1..30] of double; paired, structured:boolean; ref:integer; end;
TData3 = TDictionary; // по имени референса TData1 = class(TDictionary); по хромосоме и позиции, ключ строится, как описано выше // переменные и методы класса, к данным первого уровня удобно обращаться без разъименования. end;
И встречный вопрос: ключ в TData3 и name в DataType у вас не одно и то же?

Можно ли данные в дереве TDictionary писать в файл, как массив?

Вопрос, непосредственно связанный с моим предыдущим Импорт данных секвенирования и обработка SAM-файлов в TDictionary
Ранее, когда мы держали данные для обработки в массиве записей, мы просто создавали типовой файл и сбрасывали данные (а затем архивировали в ZIP, хорошо сжималось):
type data = record <...> end; var f: file of data; d: array of data;
Теперь, если мы будем использовать структуру
type DataType = record name,qual, info, seq:string; data:array[1..30] of double; paired, structured:boolean; ref:integer; end;
TData3 = TDictionary; TData1 = class(TDictionary); end;
Можно ли использовать тот же подход, что и раньше, т.е. сбрасывать данные в типовой файл? Или необходимо использовать FileStream?


Ответ

Можно конвертировать в массив, но, подозреваю, что не нужно. Особенно, если вы планируете делать это лишь для записи. Гораздо проще работать с потоками. Могу привести пример, как это реализовано у нас в базовом классе:
TVCFFile = class (TDictionary) // private <...> procedure SaveToStream(stream: TStream); protected <...> public <...> procedure SaveToZip(const AFileName: string); override; procedure SaveToFile(const AFileName: string); override; end;
procedure TVCFFile.SaveToStream(stream: TStream); var posi: System.Generics.Collections.TPair; pair:System.Generics.Collections.TPair; third:System.Generics.Collections.TPair; i: Integer; writer: TWriter; begin writer := TWriter.Create(stream, 4096); try writer.WriteListBegin; for third in Self do begin writer.WriteString(third.Key); writer.WriteListBegin; for pair in third.Value do begin writer.WriteInteger(pair.Key); writer.WriteListBegin; for posi in pair.Value do begin writer.WriteString(posi.Key); writer.WriteDouble(posi.Value.qual); writer.WriteString(posi.Value.alt); writer.WriteString(posi.Value.filter); writer.WriteString(posi.Value.info); end; writer.WriteListEnd; end; writer.WriteListEnd; end; writer.WriteListEnd; finally writer.Free; end; end;
procedure TVCFFile.SaveToZip(const AFileName: string); var stream: TStream; zipFile: TZipFile; begin stream := TMemoryStream.Create; try SaveToStream(stream); stream.Position := 0; zipFile := TZipFile.Create; try zipFile.Open(AFileName, zmWrite); zipFile.Add(stream, 'bigdata.tvb'); zipFile.Close; finally zipFile.Free; end; finally stream.Free; end; end;
procedure TVCFFile.SaveToFile(const AFileName: string); var stream: TStream; begin stream := TFileStream.Create(AFileName, fmCreate); try SaveToStream(stream); finally stream.Free; end; end;
Можно просто записать в файл, можно сразу в ZIP-файл, скорость записи и считывания достаточно велика (для загрузки есть аналогичные методы, строите их от обратного). Плюс, понадобятся методы для загрузки из SAM, записи в него же, возможно, понадобится поддержка BED, VCF и прочее, а, может, вы всё это сделаете в других классах.

Архитектура приложения android [закрыт]

Расскажите как правильно составлять архитектуру приложения?
Как его спроектировать?
С чего прежде всего нужно начать при разработке, как всё распределить и раставить по полочкам,где можно накидать макеты на каждый Activity?


Ответ

Лично на своем опыте скажу. Ввиду наличия в начале пути только задумки и некоторых представлений по структуре веб-приложений, "архитектура androidприложения" выглядела вполне себе "ясно". По мере изучения java, android приходилось эту самую архитектуру перессматривать. Плюс появляются идеи как улучшить приложение, что-то добавить, о чем даже не мог подумать в свое время.
Если сравнить ответы на вопрос "Как это сделать лучше?" в начале построения приложения, когда опыта мало и в конце, когда опыта уже побольше, но все равно так мало, то это будут очень разные ответы.
Итог.
Все ответы нужно искать исходя из поставленной задачи. Чем больше опыта тем относительно прямолинейнее построение и реализация архитектуры android приложения. Накидывать макеты можно просто на бумаге. Макет лично мне подсказывает только направление. Очень много библиотек, которые уже решают определенную задачу. Нужно только знать об их существовании и подключить. ОЧЕНЬ помогает теория, а также StackOverflow, Google и радость от того, что что-то уже получается, работает.

Путь к файлу процесса c#

Получаю список процессов
System.Diagnostics.Process[] procList = System.Diagnostics.Process.GetProcesses();
Как узнать папку, где находится этот процесс ? Пытался так
procList[0].MainModule.FileName - возвращает null
procList[0].StartInfo.FileName - возвращает пустую строку
Есть еще способы ?


Ответ

Если Вам нужно получить путь программы откуда запускаете свой файл:
using System.Linq; using System.Diagnostics;
try { foreach (var proc in Process.GetProcesses().Where(p => !string.IsNullOrEmpty(p.MainWindowTitle)).ToList()) { Console.WriteLine(proc.MainModule.FileName); } } catch { /*Тут ловим исключения*/ }
Так же без использования Linq
Console.WriteLine(Process.GetCurrentProcess().MainModule.FileName);
Имя запускаемого файла можно узнать так:
Console.WriteLine(Path.GetFileName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName));
Чтобы перечислить все папки через процессы можно воспользоваться таким способом:
foreach (Process instance in Process.GetProcesses()) { try { Console.WriteLine(instance.ProcessName); Console.WriteLine(instance.MainModule.FileName); } catch (System.ComponentModel.Win32Exception w32ex) { Console.WriteLine(w32ex.Message); } catch (Exception ex) { Console.WriteLine(ex.Message); } }
Если же Вы хотите получить все папки процессов можно воспользоваться через WMI
using (var mCollection = new ManagementClass("Win32_Process").GetInstances()) { foreach (ManagementObject process in mCollection) { Console.WriteLine((string)process["ExecutablePath"]); //Console.WriteLine(FileVersionInfo.GetVersionInfo((string)process["ExecutablePath"]).FileDescription); } }

Перенаправление потока вывода и потока ошибок в конец файла

Можно перенаправить поток вывода и(или) ошибок в файл с его перезаписью: 1>file выведет данные с потока вывода в файл с его созданием или перезаписью 2>file выведет данные с потока ошибок в файл с его созданием или перезаписью 1&>file (и несколько других вариантов) выведут данные и с потока вывода и с потока ошибок в файл с его созданием и перезаписью.
Можно выводить поток вывода или поток ошибок в файл, записывая в его конец:
1>>file 2>>file
Но если попробовать сделать что-то вроде 1&>>file, то выскочит синтаксическая ошибка.
Как можно записывать в конец файла и с потока вывода и с потока ошибок?


Ответ

Например в Bash так:
$ { echo "stdout text"; echo "stderr text">&2; } >> file 2>&1 $ cat file stdout text stderr text
Bash выполняет перенаправление слева направо:
>>file: открывает file в режиме дозаписи и перенаправляет туда стандартный вывод (stdout) 2>&1: перенаправляет вывод ошибок (stderr) туда, куда в настоящий момент выводится стандартный вывод, т.е. в открытый ранее файл file
cmd 2>&1 >> file перенаправит только стандартный вывод в file, т.к вывод ошибок будет перенаправлен на стандартный вывод до того, как последний будет перенаправлен в файл:
$ { echo "stdout text"; echo "stderr text">&2; } 2>&1 >> file stderr text $ cat file stdout text

Вызов функции из dll написанной на delphi из python

Импортировал ctypes, подключился к dll. Есть например такая функция:
function GetStatusCardReader(var StatusCardReader: Word): Integer; stdcall;
Пробую делать так:
from ctypes import *
libc = windll.LoadLibrary('C:\test.dll')
func = libc.GetStatusCardReader func.restype = c_short print(func)
Получаю на выходе <_FuncPtr object at 0x057ABA08>
Как получить значение?


Ответ

Чтобы получить значение, функцию надо вызвать.
import ctypes
_dll = ctypes.windll.test # загрузка test.dll из текущего каталога GetStatusCardReader = _dll.GetStatusCardReader
GetStatusCardReader.argtype = ctypes.POINTER(ctypes.c_uint16) GetStatusCardReader.restype = ctypes.c_int32
StatusCardReader = ctypes.c_uint16(5) # инициализация параметра некоторым значением Result = GetStatusCardReader(ctypes.byref(StatusCardReader)) # вызов функции
print(StatusCardReader.value) print(Result)
Поскольку StatusCardReader в прототипе функции объявлена как var, передавать её надо по ссылке, используя ctypes.byref

Как получить содержимое ссылок?

Подскажите пожалуйста как получить содержимое ссылок c BeautifulSoup(html, 'lxml')? Не сами ссылки а название! есть вот такой код:
html = urllib.request.urlopen('https://kyxni.pro/katalog/') soup = BeautifulSoup(html, 'html.parser').find('div', class_='builder-posts-wrap') for i in soup.find_all('h2', class_='post-title'): print(i)
выводит ссылки:

Кухня ЭЛЕГИЯ

Кухня ДИАНА

Кухня ТЕМЗА


а я хочу получить сами названия:
Кухня ЭЛЕГИЯ Кухня ДИАНА Кухня ТЕМЗА и т.д.
Подскажите пожалуйста как это реализовать?
И как можно открыть сохранённую страницу, что бы каждый раз сайт не грузить? Такая конструкция в коде который выше не работает
html = open('kuhni.html').read()


Ответ

а я хочу получить сами названия:
for i in soup.find_all('h2', class_='post-title entry-title'): print(i.text)
Когда нужно получить текстовое содержимое, применяйте атрибут text (только не к списку, который возвращается методом find_all).
И как можно открыть сохранённую страницу, что бы каждый раз сайт не грузить? Такая конструкция в коде который выше не работает
У меня получилось так:
html = open('kuhni.html', encoding='utf8').read()
P.S. На будущее. Приводите текст ошибок.

Как закрыть приложение в Android

У меня приложение выполняется в главном активити MainActivity а мне нужно, чтобы приложение закрывалось через пункт меню настроек. Я пробовал вот так вызывать в классе settings extends PreferenceActivity но ничего не происходит:
Preference pfinish = (Preference)findPreference(getString(R.string.settings_finish)); pfinish.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener(){ @Override public boolean onPreferenceClick(Preference preference) { MainActivity mp = new MainActivity(); mp.finish(); return true; } });
Вообще, во многих пограммах есть пункт Exit как это сделать?


Ответ

Если это единственное открытое activity в приложении, то можно использовать просто:
finish();
без обращения к какому-либо экземляру. Чтобы закрыть приложение с любым количеством activity есть:
android.os.Process.killProcess(android.os.Process.myPid());
Но вам скорее всего подойдет и finish()

Метрика для телеграм-бота (сбор статистики)

Требуется обложить метрикой бота для телеграм. Нашел сайт http://botan.io и не понимаю, жив ли проект... Актуален ли сегодня проект botan.io? У ресурса в футере указан 2015 год. И есть ли альтернатива?


Ответ

Хороший вопрос. Увы - проект мёртв, как это можно понять по активности его репозитория на гитхабе.
В декабре написал разработчикам. Сказали, что проект на данный момент не поддерживают, поэтому даже в pull request нет смысла. По датам возобновления работы над сервисом не сказали.
Неизвестно, что именно послужило причиной сворачивания, но у проекта были проблемы с роскомнадзором и блокировками. Альтернатив не нашёл, к сожалению. С удовольствием премирую того, кто предложит адекватную альтернативу.

UPD
У меня две хорошие новости:
Апи ботана работает Можно пользоваться апи ботана с токеном, полученным непосредственно в метрике (проверено опытным путём)
Для бота будет актуальным, думаю, только один метод - track. Для этого можно юзать обычные нативные веб-запросы, без обёрток - никаких зависимостей от конкретных реализаций.
Пример запроса:
// token = qwerty; // chatID = 12345; // command = 'start';
https://api.botan.io/track?token=token&uid=chatID&name=command
где:
token - токен приложения, выданный метрикой (или ботом, если это настолько старый токен); uid - идентификатор, позволяющий разделить источники событий или наоборот, сгруппировать их (может быть любым уникальным значением, да даже и не уникальным - на усмотрение разработчика); name - наименование (произвольное) отслеживаемого действия пользователя
Track message (метод Shorten url не работоспособен на территории РФ по причине блокировки домена, возвращающего "короткие" ссылки)

Возможные альтернативы:
chatbase.com botanalytics.co dashbot.io botlytics.co

Свойство зависимости из UserControl в MainWindow

Не работает свойство зависимости
UserControl.cs:
// private double Radius = 100; private void DrawScale() { double bigTick = 9; for (double i = 0; i <= 90; i = i + bigTick) { Point p = new Point(0.5, 0.5); Rectangle r = new Rectangle { Height = 5, Width = 15, Fill = new SolidColorBrush(Colors.Aqua), HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, RenderTransformOrigin = p };
TransformGroup trGp = new TransformGroup(); RotateTransform rTr = new RotateTransform(); double iRadian = (i * Math.PI) / 180; rTr.Angle = i; trGp.Children.Add(rTr); TranslateTransform tTr = new TranslateTransform(); tTr.X = (int) ((Radius) * Math.Cos(iRadian)); tTr.Y = (int) ((Radius) * Math.Sin(iRadian)); trGp.Children.Add(tTr); r.RenderTransform = trGp; gr.Children.Add(r); } }
public double Radius { get { return (double)GetValue(MyPropertyProperty); } set { SetValue(MyPropertyProperty, value); } }
public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register("Radius", typeof(double), typeof(RoundScale), null);
userControl.xaml

MainWindow.xaml

Если переменную Radius в UserControl.cs разкомментировать и удалить из кода свойство зависимости то все работает как надо.


Ответ

Вы неправильно определили dependency property. CLR-свойство должно называться так, как ваше dependency property, минус суффикс Property. В вашем случае dependency property называется MyPropertyProperty, а CLR-свойство — Radius
Переименуйте dependency property в RadiusProperty

Документация: https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/custom-dependency-properties#checklist-for-defining-a-dependency-property
When you create the identifier field, name this field by the name of the property as you registered it, plus the suffix Property

Ещё одна проблема — опрос dependency property из конструктора. Дело в том, что значение dependency property, заданное непосредственно в XAML, устанавливается в InitializeComponent, а привязки могут сработать ещё позже. Поэтому имеет смысл либо читать значение на событии Loaded, либо подписаться на изменения.

Если вам нужно подписаться на изменения, проще всего указать callback в определении dependency property:
public double Radius { get { return (double)GetValue(RadiusProperty); } set { SetValue(RadiusProperty, value); } }
public static readonly DependencyProperty RadiusProperty = DependencyProperty.Register( "Radius", typeof(double), typeof(RoundScale), new PropertyMetadata(0.0, OnRadiusChangedStatic));
static void OnRadiusChangedStatic(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((RoundScale)d).OnRadiusChanged();
void OnRadiusChanged() { // тут у вас поменялся радиус, реагируйте }

Странности поведения FOR ORDINALITY для json_table с nested path в oracle 12.1

Имею json вида:
[ { "debitOverturn": "939.34", "table": [ { "debit": "", "credit": "939.34" }, { "debit": "939.34", "credit": "" } ] }, { "debitOverturn": "939.34", "table": [ { "debit": "", "credit": "939.34" }, { "debit": "939.34", "credit": "" } ] } ]
Делаю к нему запрос (на oracle 12.1):
SELECT jt.u_lvl, jt.debitOverturn, jt.l_lvl, jt.debit, jt.credit FROM some_table s, JSON_TABLE (s.clob_for_json,'$[*]' COLUMNS ( u_lvl FOR ORDINALITY, debitOverturn VARCHAR2(20) PATH '$.debitOverturn', NESTED PATH '$.table[*]' COLUMNS ( l_lvl FOR ORDINALITY, debit VARCHAR2(38) PATH '$.debit', credit VARCHAR2(38) PATH '$.credit'))) AS jt WHERE s.hash = :l_hash
и получаю довольно странный результат для счетчика:
U_LVL DEBITOVERTURN L_LVL DEBIT CREDIT 1 939.34 1 (null) 939.34 2 939.34 2 939.34 (null) 3 939.34 1 (null) 939.34 4 939.34 2 939.34 (null)
т.е. U_LVL считает строки не своего уровня, а вообще все.
Повторяю запрос на домашней виртуалке с 12.2 - результат ожидаемый:
U_LVL DEBITOVERTURN L_LVL DEBIT CREDIT 1 939.34 1 (null) 939.34 1 939.34 2 939.34 (null) 2 939.34 1 (null) 939.34 2 939.34 2 939.34 (null)
Самое смешное, что при повторе запроса на оракловском livesql.oracle.com, результат еще страньше:
U_LVL DEBITOVERTURN L_LVL DEBIT CREDIT 1 939.34 1 (null) 939.34 1 939.34 2 939.34 (null) 1 939.34 1 (null) 939.34 1 939.34 2 939.34 (null)
Это как вообще понимать? Баг? Поведение ORDINALITY настраивается где-то?


Ответ

В итоге оказался баг в json_table, если кому интересно, для исправления нужно установить патч на 12.1.0.2.0, на 12.2 уже исправлено.

Golang: Gorilla websocket, состояние подключения

Есть такая функция
func WsHandler_remote_1(w http.ResponseWriter, r *http.Request) { quit := make(chan int) conn, err := wsupgrader.Upgrade(w, r, nil) go db.CreateChanelNotify(conn, 1, quit) defer conn.Close() if err != nil { fmt.Println("Failed to set websocket upgrade: %+v", err) return } for { t, msg, err := conn.ReadMessage() if err != nil { fmt.Println("!!") break }
conn.WriteMessage(t, msg) } }
Как определить что соединение закрылось (при обрыве связи, или если клиент закрыл браузер)


Ответ

Вам нужно проверить, является ли тип возвращаемой ошибки *websocket.CloseError
t, msg, err := conn.ReadMessage() if err != nil { if err, ok := err.(*websocket.CloseError); ok { log.Printf("connection closed, code: %d, text: %q", err.Code, err.Text) break } break }
Подробнее:
http://www.gorillatoolkit.org/pkg/websocket#CloseError http://www.gorillatoolkit.org/pkg/websocket#constants

Как реализовать загнутый уголок?


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


Ответ

Собственно ваш вопрос в этом border-bottom-left-radius: 20px; в .marker:before ?
* { box-sizing: border-box; } .marker { width: 300px; height: 300px; background: tomato; padding: 10px; border-radius: 20px; position: relative; } .border { width: 100%; height: 100%; border: 3px dashed orange; border-radius: 20px; } .marker:before { content: ""; border-top: 50px solid #fff; border-right: 50px solid #fff; border-bottom: 50px solid orange; border-left: 50px solid orange; position: absolute; top: 0; right: 0; border-bottom-left-radius: 20px; }


для экспериментов : https://codepen.io/topicstarter/pen/vpPEeW

Проблема с модальными окнами

Всем здравствуйте! Недавно начал изучать основу вёрстки. Верстал по макету и столкнулся с двумя проблемами.

На скриншоте видно, что подчёркивание точками обозначено шире надписи "Смотреть работу". Как можно выровнить подчёркивание, чтоб оно шло ровно по ширине текста? Проблема с модальными окнами. При нажатии на ссылку "Смотреть работу" должно выходить модальное окно с изображением и описанием.

Но у меня выходит только окно с одной надписью "Описание проекта" больше ничего.
P.S: В самом видео, по которому делал вёрстку, данных проблем не возникало, всё работало чётко и плавно. Также автор данного видео оставил ссылку для загрузки файла с данной вёрсткой, который сверстал на видео. И там также присутствуют эти же проблемы, хотя на видео, как я уже оговаривал, всё хорошо работает. В чём может быть проблема?
body { font-family: 'Open Sans', sans-serif; } html { font-size: 10px; } a:active, a:visited, a:focus { text-decoration: none; outline: none; } .wrapper { display: table-cell; vertical-align: middle; } .main { position: relative; display:table; width: 100%; text-align: center; color: #fff; height: 100vh; background: #000 url(../img/main-bg.jpg) center center no-repeat; } .main-overlay { position: absolute; z-index: 1; width: 100%; height: 100%; background-color: rgba(0,0,0,0.5); } .main h1 { margin-bottom: 1.4rem; font-weight: 300; text-transform: uppercase; font-size: 4.8rem; } .main p { font-size: 3rem; font-weight: 300; } .main-header { position: relative; z-index: 2; } .main-line { width: 200px; height: 1px; background-color: #fff; margin: 0 auto; } .main-down { position: absolute; color: #fff; z-index: 4; bottom: 2rem; display: inline-block; font-size: 2rem; width: 50px; height: 50px; border-radius: 50%; border: 1px solid transparent; line-height: 50px; left: 50%; margin-left: -25px; transition: 0.2s; } .main-down:hover { color: #fff; border-color: #fff; } /* Секция с портфолио */ .portfolio { padding: 10rem 0px; text-align: center; } .section-header { text-transform: uppercase; font-weight: 800; font-size: 3.6rem; margin-bottom: 5rem; } .portfolio img { width: 100%; max-width: 360px; box-shadow: 0px 4px 29px 0px rgba(87, 92, 97, 0.54); } .portfolio a { display: block; margin: 2rem auto 6rem; color: #333; width: 17rem; border-bottom: 1px solid transparent; } .portfolio a:hover { text-decoration: none; border-bottom: 1px dotted #333; } /* Секция - подвал (footer) */ .footer { background-color: #646464; color: #fff; text-align: center; padding: 3rem 0; } .footer strong { font-weight: 300; font-size: 2.4rem; } .social-links { margin-top: 1rem; } .social-links a { width: 5rem; height: 5rem; line-height: 5rem; display: inline-block; color: #fff; border: solid 1px #fff; border-radius: 50%; margin-left: 1rem; margin-right: 1rem; font-size: 2rem; transition: 0.2s; } .social-links a:hover { background-color: #fff; color: #646464; } .offer-btn { display: block; width: 80%; max-width: 200px; margin: 1rem auto; border: 1px solid #fff; padding-top: 1rem; padding-bottom: 1rem; color: #fff; border-radius: 100px; transition: 0.2s; } .offer-btn:hover { text-decoration: none; background-color: #fff; color: #646464; } .modal img { width: 100%; } .modal-title { font-weight: 800; font-size: 2rem; } .close { background-color: transparent; border: none; font-size: 2.5rem; position: absolute; right: 2rem; top: 1rem; } .modal-btn { display: inline-block; color: #333; border: 1px solid #333; padding: 10px 20px; border-radius: 5px; } .modal-btn:hover { background-color: #333; color: #fff; text-decoration: none; } Кази Рустамов - Портфолио

Кази Рустамов

Верстка на HTML и CSS
Разработка сайтов под ключ



Ответ

Всё потому что в видео в котором ты смотришь, он использует функцию load в JQuery котором загрузка контента модального окна идет с отдельного .html файла.
А он работает только если запущен сервер, и локально он работать не будет. Запусти какой нибудь локальный сервер и всё заработает.
А насчет ссылок, сделай ссылку строчно-блочной, и обводка будет точно по размеру самого текста.

Почему в таблице при `border-collapse: separate` не отображается border-top у thead?

Если я ставлю параметр border-collapse: collapse, то border - видно. Чем регулируется это поведение?
table { width: 100%; border-collapse: collapse; } thead { border-top: solid 1px; }

 2013 20142015
Нефть43 5179
Золото29 3448
Дерево38 5736

Иначе:
table { width: 100%; border-collapse: separate; } thead { border-top: solid 1px; }
 2013 20142015
Нефть43 5179
Золото29 3448
Дерево38 5736


Ответ

border-collapse - устанавливает, как отображать границы вокруг ячеек таблицы.
[collapse] - линия между ячейками отображается только одна.
[separate] - вокруг каждой ячейки отображается своя собственная рамка, в местах соприкосновения ячеек показываются сразу две линии.
Так как явно не задан цвет границы, то при collapse(должна отобразиться одна граница) взят цвет по умолчанию (black) и отображается граница в table, а не в thead. Учитывается border в thead, tbody, tfoot и tr
При separate игнорируются border в thead, tbody, tfoot и tr

Верстка css button, как сверстать такую кнопку?

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

у меня что то получилось, вот только по бокам как сделать, подскажите
.button { display: inline-block; border: none; color: #fff; text-decoration: none; background-color: #ffb700; padding: 26px 45px; text-transform: uppercase; font-weight: 600; letter-spacing: 3px; border-radius: 32px; text-align: center; position: relative; outline: 0; transition: background-color .1s ease; } .button::after { transition: background-color .2s ease; position: absolute; content: ''; height: 4px; bottom: 0; width: 100%; background-color: #5f4004; opacity: .18; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; left: 0; } .button:active::after { opacity: .32; } .button:hover::after { opacity: .22; } .button:hover { background-color: #fea60d; } Бесплатный расчет


Ответ

Это делается с помощью внутренней тени. Цвет уже под себя настраивайте
.button { display: inline-block; border: none; color: #fff; text-decoration: none; background-color: #ffb700; padding: 26px 45px; text-transform: uppercase; font-weight: 600; letter-spacing: 3px; border-radius: 32px; text-align: center; position: relative; outline: 0; transition: background-color .1s ease; box-shadow: inset 0 -5px 0 0 #aaa; /* тень */ } .button:hover { background-color: #fea60d; } Бесплатный расчет

Глобальное нажатие на кнопки во vue.js

Доброго времени суток.
Не могу найти инфо, о том, как можно отслеживать нажатие на клавиши.
Что я имею ввиду:
$('html').keydown(function(e){ //отлавливаем нажатие клавиш if (e.keyCode == 13) { //если нажали Enter, то true alert("Ура нажали Enter"); } });
Вот пример кода на jquery как мы могли отслеживать глобальное нажатие на enter, как можно подобное организовать на vue?
Спасибо


Ответ


Придумал как запилить такую штуку, пора уже покупать себе уточку и ей задавать вопросы :)
Вот таким макаром решил:
const app = new Vue({ el: '#app',
created() { document.addEventListener('keydown', this.onKeyDown) },
beforeDestroy() { document.removeEventListener('keydown', this.onKeyDown) },
methods: { onKeyDown(e) { console.log('keydown!'); console.log(e.target); } }, });
Суть в том, что вьюха уже сама себе забиндила клавиши и нужно сначала удалить ивент, а потом добавить свой.

Заполнение двумерного массива / Векторизация текста

Нужно заполнить двумерный массив. элемент с индексом (i, j) в этой матрице должен быть равен количеству вхождений j-го слова в i-е предложение. (предложения считываются из файла, разбиты на списки и все слова, встречающиеся в предложениях добавлены в словарь d, где ключ - это слово, а порядковый индекс значение).
входные данные 22 предложения, приведенных к спискам вида ['in', 'comparison', 'to', 'dogs', 'cats', 'have', 'not', 'undergone', 'major', 'changes', 'during', 'the', 'domestication', 'process'] в итоге должна получиться матрица 22х253 (22 - как предложений, 253 как всего уникальных слов, используемых в предложениях). Слова собраны в словарь вида [слово: индекс]. Если слово из словаря встречается в 1 предложении 2 раза, а его индекс по словарю 1, на месте элемента m[1, 1] должна стоять 2 и т.д.
Создала пустую матрицу и запустила перебор, но она все равно остается нулевой, не пойму где ошибка
m = np.zeros((number_line, len(new_line))) i = 0 for line in f.readlines(): for x in line: a = line.count(x) j = d[x] m[i, j] = a i += 1


Ответ

По просьбе автора вопроса привожу пример решения с циклами.
import numpy as np from nltk.tokenize import sent_tokenize, RegexpTokenizer from collections import Counter
text = """Displays osx displays. osx selection. Nothing! """ sentences = sent_tokenize(text) tok = RegexpTokenizer('(?u)\\b\\w\\w+\\b') vocab = {'displays':0, 'osx':1, 'selection':2}
res = np.zeros((len(sentences), len(vocab))) for i,s in enumerate(sentences): for w,cnt in Counter(w.lower() for w in tok.tokenize(s)).items(): if w in vocab.keys(): res[i, vocab[w]] = cnt
Результат:
In [254]: res Out[254]: array([[ 2., 1., 0.], [ 0., 1., 1.], [ 0., 0., 0.]])
In [255]: vocab Out[255]: {'displays': 0, 'osx': 1, 'selection': 2}
NOTE: для реальных задач лучше воспользоваться другим решением

Vim превратил табулатор в пробелы после отключения expandtab

Вот здесь я спрашивал про одну ошибку. Причиной ошибки оказалось, что вместо табулятора ввелись пробелы.
Я выполнил в viм - :set noexpandtab, чтобы не было пробелов. Ввёл клавишей табулятор и затем EOF.
А в файле после сохранения действительно пробелы:
~$ xd tabs 000000 20 20 20 20 45 4f 46 0d 0a > EOF..<
Устранил ошибку с Ctrl-V+Tab
Почему viм превратил табулятор в пробелы после noexpandtab?


Ответ

В вашем случае просто получился такой вариант: softwidth < tabstop. Смотрите!
На ввод пробельных символов (которые обычно отображатся в виде пропуска в тексте) клавишей TAB в Vim влияют упомянутый вами параметр expandtab, но также softwidth и tabstop следующим образом. При активированном noexpandtab (это ваш случай) при нажатии на клавишу табуляции редактор вычисляет ближайшую позицию для вставляемого отступа, которой задаётся настройкой softwidth, затем вставляет столько символов табуляции, чтобы не выйти за новую рассчитанную позицию курсора, считая при этом '\t' (U+0009) по ширине эквивалентным tabstop пробелам. Остальное пространство заполняется обычными пробелами.
Возможно, это выглядит слишком замудрёно, но рассмотрим пример. Допустим, softwidth=2, tabstop=4, ваш редактор находится в режиме вставки, а курсор стоит в начале строки (в колонке №1). Вы нажимаете на клавиатуре клавишу TAB и вставляются два обычных пробела ' ' (U+0020), а курсор переходит в колонку №3. Вы второй раз нажимаете на табуляцию — эти пробелы заменяются на одну '\t' (курсор в 4 колонке). Нажмите в третий раз — получите одну табуляцию, а за ней два пробела (теперь курсор в 6 колонке). Четвёртое нажатие приведёт к вводу двух символов табуляции и т.д.
Иными словами, нажатие TAB заставляет редактор увеличить отступ курсора на единицу, но ширина одного отступа задаётся настройкой softwidth. А ширина одного символа табуляции настраивается с помощью tabstop.
Поэкспериментируйте с конфигурацией Vim, а легко различать табулиции '\t' от пробелов ' ' вам поможет примерно такая команда для подсветки пробельных символов.
set list lcs=tab:>\ ,space:.

Что за концепт friend class?

Добрый день. Перешел на новую работу, работа заключается в интеграции с системой SAP ERP. Там есть понятие Friend class. Есть ли его аналог в Java?
Сколько программирую, ещё такого понятия не встречал.


Ответ

friend - дружественный из арсенала C++.
The friend declaration appears in a class body and grants a function or another class access to private and protected members of the class where the friend declaration appears.
по сути класс или метод, который имеет доступ к приватным и защищенным членам класса.
В Java такого понятия нет.

Какой вариант проверки условия наиболее производителен?

int a = 0; String b = "0";
вариант:
if(String.valueOf(a).equals(b)) {} вариант:
if(Integer.valueOf(b) == a) {}


Ответ

Пример кода:
int[] a = new int[1000000]; String[] b = new String[1000000]; for(int i = 0; i < 1000000; i++){ a[i] = i; b[i] = "8"; } long start = System.currentTimeMillis();
for(int i = 0; i < 1000000; i++){ if(String.valueOf(a[i]).equals(b[i])){
} }
System.out.println(System.currentTimeMillis() - start); start = System.currentTimeMillis();
for(int i = 0; i < 1000000; i++){ if(Integer.valueOf(b[i]) == a[i]){
} } System.out.println(System.currentTimeMillis() - start);
Результаты в мс (4 запуска):
1 вариант: 203 | 156 | 484 | 140
2 вариант: 32 | 47 | 47 | 32

Формула в строку Java

Задача: Составить таблицу значений функции y = f(x) на отрезке [n; m] с шагом k
Собственно вопрос возникает в моменте. Как ввести f(x). Ибо сама формула (для примера х-2), является строкой, а значение Y числом. т.е. Через сканер вводим все значения n,m,k и саму формулу "x-2" или любую другую. И в коде эту формулу применяем для подсчета значение Y.
while(x<=r.m){ y=x-5; System.out.println("x = " +x+" y = "+ y); x=x+r.k; }
В данном случае у меня стоит формула, введенная изначально "y=х-5" (вторая строчка, введено топорно, прямо в код), а мне надо, чтоб программа считала ту, которую я введу через сканер.
upd. После большого количества прочитанного и опробованного, хочется добавить, что введеное через сканер представляет собой цисловые значения, букву X и знаки арифметических вычислений ("+","-","/","*").


Ответ

Решение ленивого человека выглядит так:
import javax.script.*;
public class Eval { public static void main (String[] args) throws Exception { ScriptEngineManager engineManager = new ScriptEngineManager(); ScriptEngine engine = engineManager.getEngineByName("nashorn"); engine.put("x", 1); System.out.println(engine.eval("x * 2 + 1")); } }
В Java есть полноценный движок JavaScript (на русском), который отлично справляется с вычислением произвольных математических выражений (и не только их).
Решение же человека, которому описанная задача прилетела в виде лабораторной работы или домашнего задания выглядит сложнее. Преподаватель, скорее всего, ожидает, что вы разберёте вводимую строку на токены (переменная, оператор, число), переведёте её в обратную польскую запись, а затем вычислите, используя стековую машину (раз, два).

Чем отличаются стандарты c++14 и gnu++14?

Есть ли существенные отличия между двумя стандартами c++14 и gnu++14 (расширение GNU)? Имеет ли смысл для компиляции под линуксом придерживаться именно 2-ого варианта?


Ответ

Отличие между c++14 и gnu++14 в том, что в первом случае компилятор старается соответствовать стандарту, а во втором включает различные расширения
Если Вы пишете приложение только под линукс - то можно не задумываться о том, какой именно ключик выбирать. Если же приложение пишется так, что есть небольшая вероятность, что оно будет компилироваться и другими компиляторами (и другие платформы), то лучше указывать std=c++14. Если это приложение просто лабораторная работа, то также лучше использовать std=c++14 - в этом случае больше шансов, что у преподавателя в visual studio оно скомпилируется и можно будет получить свою оценку.

Смена языков на стороне клиента — JavaScript (jQuery)

Хочу сделать смену языка на страничке на стороне клиента. Попалась одна статья - на хабре, но примера там уже нет.
Содержимое json файлов как и в примере.
languages/eng.json
{ "hello_world":"Hello World", "some_text":"Some Text" }
languages/rus.json
{ "hello_world":"Привет Мир", "some_text":"Некоторый текст" }
Код функции из примера:
var LANGUAGE;
$.redrawLanguage = function (lang) { $.ajax({ url : 'languages/' + lang + '.json', //тянем файл с языком dataType : 'json', success : function (response) { LANGUAGE = response; //записываем в глобальную переменную, а вдруг пригодиться $('body').find("[lng]").each(function () //ищем все элементы с атрибутом { var lng = LANGUAGE[ $(this).attr('lng') ]; //берем нужное значение по атрибуту lng var tag = $(this)[0].tagName.toLowerCase(); switch (tag) //узнаем название тега { case "input": $(this).val(lng); break; default: $(this).html(lng); break; } }); } }); }
В своем примере хочу реализовать данный перевод по клику на соответствующую кнопку RU\EN:
var LANGUAGE = false; $.redrawLanguage = function (lang) { $.ajax({ url : 'languages/' + lang + '.json', //тянем файл с языком dataType : 'json', success : function (response) { LANGUAGE = response; $('body').find("[lng]").each(function () { var lng = LANGUAGE[ $(this).attr('lng') ]; var tag = $(this)[0].tagName.toLowerCase(); console.log(response + ' ' + lng); switch (tag) { case "input": $(this).val(lng); break; default: $(this).html(lng); break; } }); } }); } $.getLanguage = function (key) { if (typeof(LANGUAGE[key]) != 'undefined') { return LANGUAGE[key]; } return key; } $('#ru').on('click', function(e){ e.preventDefault(); var $this = $(this); $.redrawLanguage('eng'); }); $('#en').on('click', function(e){ e.preventDefault(); var $this = $(this); $.redrawLanguage('rus'); });

RU EN

Привет Мир Некоторый текст


Но ничего не происходит, ошибок нет и json - status 200.
console.log(response + ' ' + lng); - выводит [object Object] undefined
Как можно запустить перевод на страничке по клику на кнопку, что делаю не так? Как и с функцией $.getLanguage, как ее можно использовать,
будет нужен для того, что бы иметь возможность в произвольном месте с помощью javascript вынуть нужную строку, текущего языка,
?


Ответ

Ошибка в html-

, нужно использовать не язык, а ключ -

, а функция уже вызывается с соответствующим, нужным языком (имя нужного json файла) - $.redrawLanguage('eng'); или $.redrawLanguage('rus');
var LANGUAGE = false; $.redrawLanguage = function (lang) { $.ajax({ url : 'languages/' + lang + '.json', //тянем файл с языком dataType : 'json', success : function (response) { LANGUAGE = response; $('body').find("[lng]").each(function () { var lng = LANGUAGE[ $(this).attr('lng') ]; var tag = $(this)[0].tagName.toLowerCase(); switch (tag) { case "input": $(this).val(lng); break; default: $(this).html(lng); break; } }); } }); } $.getLanguage = function (key) { if (typeof(LANGUAGE[key]) != 'undefined') { return LANGUAGE[key]; } return key; } $('#ru').on('click', function(e){ e.preventDefault(); var $this = $(this); $.redrawLanguage('eng'); }); $('#en').on('click', function(e){ e.preventDefault(); var $this = $(this); $.redrawLanguage('rus'); console.log($.getLanguage('hello_world') ); console.log($.getLanguage('some_text') ); });

RU EN

Привет Мир

Некоторый текст

Hello World

Some Text


Конвертировать в кодировку UTF8

Есть замечательный способ создать строку уже в кодировке utf8
string str = u8"ежик"
А можно так же без лишних бубнотанцев сделать с уже готовой строкой, если я получаю её как аргумент функции?
foo("ежик"); void foo(string str) { ... }
Мне просто нужно получить строку в кодировке utf8 в string либо const char*. Можно это сделать не городя огромную стену кода?


Ответ

Не знаю насколько полезно это вам будет, но... В моём проекте под Windows присутствуют операции с кодировками cp1251 и utf8, которые покрываются такими функциями:
1251 в utf8:
string cp1251_to_utf8(const char *str){ string res; int result_u, result_c; result_u = MultiByteToWideChar(1251, 0, str, -1, 0, 0); if(!result_u ){return 0;} wchar_t *ures = new wchar_t[result_u]; if(!MultiByteToWideChar(1251, 0, str, -1, ures, result_u)){ delete[] ures; return 0; } result_c = WideCharToMultiByte(65001, 0, ures, -1, 0, 0, 0, 0); if(!result_c){ delete [] ures; return 0; } char *cres = new char[result_c]; if(!WideCharToMultiByte(65001, 0, ures, -1, cres, result_c, 0, 0)){ delete[] cres; return 0; } delete[] ures; res.append(cres); delete[] cres; return res; }
Проверка на UTF8:
bool is_valid_utf8(const char * string){ if(!string){return true;} const unsigned char * bytes = (const unsigned char *)string; unsigned int cp; int num; while(*bytes != 0x00){ if((*bytes & 0x80) == 0x00){ // U+0000 to U+007F cp = (*bytes & 0x7F); num = 1; } else if((*bytes & 0xE0) == 0xC0){ // U+0080 to U+07FF cp = (*bytes & 0x1F); num = 2; } else if((*bytes & 0xF0) == 0xE0){ // U+0800 to U+FFFF cp = (*bytes & 0x0F); num = 3; } else if((*bytes & 0xF8) == 0xF0){ // U+10000 to U+10FFFF cp = (*bytes & 0x07); num = 4; } else{return false;} bytes += 1; for(int i = 1; i < num; ++i){ if((*bytes & 0xC0) != 0x80){return false;} cp = (cp << 6) | (*bytes & 0x3F); bytes += 1; } if( (cp > 0x10FFFF) || ((cp <= 0x007F) && (num != 1)) || ((cp >= 0xD800) && (cp <= 0xDFFF)) || ((cp >= 0x0080) && (cp <= 0x07FF) && (num != 2)) || ((cp >= 0x0800) && (cp <= 0xFFFF) && (num != 3)) || ((cp >= 0x10000)&& (cp <= 0x1FFFFF)&& (num != 4)) ){return false;} } return true; }
string в wstring:
wstring string_to_wstring(string str){ wstring convertedString; int requiredSize = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, 0, 0); if( requiredSize > 0){ vector buffer(requiredSize); MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, &buffer[0], requiredSize); convertedString.assign(buffer.begin(), buffer.end() - 1); } return convertedString; }

C# Активация по нажатию клавиши на клавиатуре при свернутой форме

Как я могу продолжить работу программы по нажатию, к примеру, F12? Форма в этот момент свернута.


Ответ

Низкоуровневый перехват клавиш к Вашим услугам!) Ключ F12 - 123.
Для нахождения ключей других клавиш, можете раскомментировать строку с mBox'ом.
using System; using System.Runtime.InteropServices; using System.Windows.Forms;
namespace Whooper { public partial class Form1 : Form { private const int WH_KEYBOARD_LL = 13;
private LowLevelKeyboardProcDelegate m_callback; private IntPtr m_hHook;
[DllImport("user32.dll", SetLastError = true)] private static extern IntPtr SetWindowsHookEx( int idHook, LowLevelKeyboardProcDelegate lpfn, IntPtr hMod, int dwThreadId);
[DllImport("user32.dll", SetLastError = true)] private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("Kernel32.dll", SetLastError = true)] private static extern IntPtr GetModuleHandle(IntPtr lpModuleName);
[DllImport("user32.dll", SetLastError = true)] private static extern IntPtr CallNextHookEx( IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
private IntPtr LowLevelKeyboardHookProc( int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0) { var khs = (KeyboardHookStruct) Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct)); if (Convert.ToInt32("" + wParam) == 256) { //MessageBox.Show(khs.VirtualKeyCode+""); //Показать Ключ нажатой клавиши if ((int)khs.VirtualKeyCode==123)//123 - F12 { WindowState = FormWindowState.Normal; } } } return CallNextHookEx(m_hHook, nCode, wParam, lParam); }
[StructLayout(LayoutKind.Sequential)] private struct KeyboardHookStruct { public readonly int VirtualKeyCode; public readonly int ScanCode; public readonly int Flags; public readonly int Time; public readonly IntPtr ExtraInfo; }
private delegate IntPtr LowLevelKeyboardProcDelegate( int nCode, IntPtr wParam, IntPtr lParam);
public void SetHook() { m_callback = LowLevelKeyboardHookProc; m_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, m_callback, GetModuleHandle(IntPtr.Zero), 0); }
public void Unhook() { UnhookWindowsHookEx(m_hHook); }
public Form1() { InitializeComponent(); SetHook(); } } }
Взял из своего рабочего проекта. Если у Вас будут какие-то вопросы - решим их.

Andoid. Debuggable приложение тормозит

Условия:
Я работаю на двух компьютерах - дома и на работе. Я собираю одно и то же приложение с опцией debuggable=true Делаю я это на одном и том же девайсе.
Проблема:
При сборке на работе приложение не тормозит ни в debug buildType (будучи debuggable), ни в release buildType. Но стоит мне собрать его дома, как в debug buildType приложение начинает тормозить на экранах с тяжелой версткой (множество 'ов). А если еще и в debug-режим войти, то просто кромешный ад! При этом в release buildType все летает на тех же самых экранах.
Вопрос: Должны ли быть включены/выключены какие-то особые настройки Android Studio, чтобы оптимизировать работу debuggable приложения? (вроде и на работе и дома ставил студию одинаково, не изменяя каких-либо важных настроек). Быть может от самого компьютера зависит скорость работы приложения на телефоне (звучит фантастически, но я уже не знаю на что думать)


Ответ

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

C# WPF. Как открыть нужное окно приложения в зависимости от размера рабочего стола

Здравствуйте. Есть приложение на WPF. Хочу добавить два главных окна с различными XAML разметками. Теперь мне нужно запускать приложение в зависимости от размера рабочего стола компьютера/ноутбука.
Как определить ширину и высоту рабочего стола я знаю, делается примерно так:
int Width = SystemInformation.PrimaryMonitorSize.Width; int Height = SystemInformation.PrimaryMonitorSize.Height;
А вот как реализовать запуск нужного главного окна приложения я не знаю. Возможно ли такое вообще сделать или нет?


Ответ

Да, можно.
Откройте App.xaml и уберите установку свойства StartupUri
Затем откройте App.xaml.cs и добавьте в него метод:
protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); ... }
Вместо многоточия просто проверьте свои условия, создайте экземпляр нужного окна и покажите его:
Window window = (условие) ? new Window1() : new Window2(); window.Show();

Docker: можно ли контейнер, созданный из Windows разместить на Linux?

У нас стартап и мы все еще активно пополняемся единомышленниками, но наш продукт уже в скором времени близится к пилотному запуску. ПО наше состоит из следующих модулей:
API — проект ASP.NET Core Web API 2 MySQL Web-клиент — приложение на Angular 5. Мы не скрестили ASP.NET Core и Angular, а разрабатываем веб-клиент Angular отдельно с Node.js на борту.
Стоит задача, организовать стратегию менее безболезненного развертывания всех трех узлов на инфраструктуре клиента, естественно с учетом того что будет написан туториал по инсталяции и что установкой будет заниматься техническая служба клиента.
Операционная система, которая будет крутиться на сервере клиента неизвестна и хотелось сделать некий универсальный процесс инсталяции который подходил бы как на Windows так и для Linux. Понятное дело, что за универсальность надо платить.
Как писал выше, мы только развивающийся отряд, и мы не имеем пока еще в арсенале хорошего специалиста-администратора с большим опытом решения подобных задач по развертыванию.
Docker. Докер, Docker и еще раз Докер. Естественно в первую очередь программисту приходит в голову это ПО одной из задач (я сказал одной из) которого является избавить программиста от проблем развертывания и дать максимально сфокусироваться на кодинге. Ох если бы это было так.
Прокси-сервер. И как не крути, но плюс к Kestrel/HTTP.sys какой-то из серверов Apache, IIS, nginx и т.д. все же нужен на сколько понял я. Даже если клиент планирует работать с нашим продуктом только внутри корпоративной сети. Дела с HTTP.sys конечно лучше: он не такой голый как Kestrel, но у нас то речь об универсальности, а HTTP.sys только для Windows. Пытался к примеру установить nginx на Windows Server в качестве эксперимента: мама родная, со стороны казалось, что я в первый раз вижу компьютер).

И если можно я задал бы два вопроса:
1) Первый вопрос он более общий, вы наверное догадались: что посоветуете?
2) А теперь, чтобы конкретизироваться: я сейчас работаю на Windows 10 и если я задумал использовать Docker, то я ведь правильно понимаю, что мне надо создать четыре контейнера
Контейнер с прокси-сервером (Apache, nginx или IIS) Контейнер с СУБД MySQL Контейнер с Angular-приложением Контейнер с проектом ASP.NET Core 2 Web API
Можно ли это сделать прямо из Windows? То есть будет ли работать контейнер созданный на Windows-машине на Linux?


Ответ

Docker под Windows может работать в двух режимах - Windows Containers и Linux Containers. Режимы переключаются через иконку в трее:

В режиме Windows Containers он собирает и хостит контейнеры прямо в текущей операционке. Собранные в этом режиме контейнеры нельзя разместить под Linux.
В режиме Linux Containers он на самом деле собирает и запускает контейнеры на линуксовой виртуалке - она видна в Hyper-V Manager. Собранные в этом режиме контейнеры можно разместить под Linux.
Под каждый рантайм есть свой набор тэгов - все доступные можно посмотреть на https://hub.docker.com/r/microsoft/aspnetcore/
Т.е. да, вы можете включить режим Linux Containers, собрать набор из 4-х контейнеров (взяв nginx в качестве прокси), и потом запустить все это под Linux.

Как сделать полоску на элементе меню, как у гугла и icons8

Как сделать полоску на элементе меню такую же, как на картинках?


Ответ

Вариант с border
* { margin: 0; padding: 0; } body { font-family: Monospace, sans-serif; } .container { padding: 0 15px; } li { list-style-type: none; } a { text-decoration: none; color: black; text-transform: uppercase; } .menu { padding-top: 15px; background-color: crimson; } .list { display: flex; justify-content: flex-end; } .list li { padding-bottom: 15px; margin-left: 15px; } .active { border-bottom: 2px solid black; } .list li:hover { border-bottom: 2px solid black; }


Найти количество страниц книги, если дана сумма цифр номеров страниц

Здравствуйте. Есть такая интересная задачка:
Сумма цифр номеров страниц в книге равна 1050 Сколько страниц в книге?
Как просчитать ответ?


Ответ

У каждого числа, обозначающего страницу, имеется цифра на месте единиц. При n страниц имеется n цифр, стоящих на месте единиц. У всех, за исключением первых 9 страниц, числа являются как минимум двухзначными. Поэтому добавим еще n-9 цифр. У всех, за исключением первых 99 страниц, числа являются трехзначными, что добавляет еще n-99 цифр. n+(n-9)+(n-99) = 1050 при его решении получаем 386. Видимо, не на всех страницах стоял номер...

Потокобезопасная проверка состояния

Задача: Есть клиенты, которые подключаются к серверу и периодически выполняют какие-то операции. Если за некоторое время клиент не провел ни одной операции, то в базе его статус меняется на оффлайн. При возобновлении операция статус в БД меняется на онлайн. Клиенты живут в разных потоках. Нагрузка:
Клиентов порядка 100-200 средняя частота операций порядка секунды-двух время бездействия: 5 минут Алгоритм:
Есть Map у которого ключ - это ID клиента, а значение - время истечения ожидания. Клиенты сдвигают это время при каждом обращении к серверу. Есть таймер, который срабатывает раз в минуту, пробегает по списку клиентов, находит тех, у которых истекло время ожидания, удаляет их из списка и меняет статус в базе. Реализация:
public class ActiveClientManager implements Consumer { private final Map clients; private final PoolDataSource pds; private final long timeout; private final Object dbMonitor;
public ActiveClientManager(PoolDataSource pds, long timeout) { clients = new ConcurrentHashMap<>(); this.pds = pds; this.timeout = timeout; dbMonitor = new Object(); }
// Действие клиента @Override public void accept(Integer clientID) { // Время после которого, клиент уходит в оффлайн long offlineTime = System.currentTimeMillis() + timeout; // Вставляем нового клиента, или обновляем существующего if (clients.put(clientID, offlineTime) == null) { // Если была произведена вставка, то меняем статус в базе try { try (Connection con = pds.getConnection()) { try (PreparedStatement stmt = con.prepareStatement("UPDATE clients SET state = 1 WHERE id = ?")) { stmt.setInt(1, clientID); // Перекрываем кислород таймеру synchronized (dbMonitor) { stmt.executeUpdate(); } } } } catch (SQLException e) { e.printStackTrace(); } } }
// Обработка события таймера public void testTimeout() throws SQLException { long currentTime = System.currentTimeMillis(); // Сюда занесем всех клиентов, которые уже отвалились List removeClients = new ArrayList<>(); clients.replaceAll((key, val) -> { if (val <= currentTime) { // если время уже прошло, то сохраняем нашего клиента removeClients.add(key); // и удаляем его из общего списка return null; } // иначе ничего не трогаем return val; }); // если есть кого удалять if (removeClients.size() > 0) { try (Connection con = pds.getConnection()) { try (PreparedStatement stmt = con.prepareStatement("UPDATE clients SET state = NULL WHERE id = ?")) { // блокируем добавление нового клиента synchronized (dbMonitor) { for (Integer client : removeClients) { // если клиент не появился опять в общем списке if (!clients.containsKey(client)) { // то сбрасываем ему статус stmt.setInt(1, client); stmt.executeUpdate(); } } } } } } } }
Собственно вопрос - не упустил ли я, что-либо в синхронизации?
Update
Выяснилось, что конструкция
clients.replaceAll((key, val) -> { if (val <= currentTime) { // если время уже прошло, то сохраняем нашего клиента removeClients.add(key); // и удаляем его из общего списка return null; } // иначе ничего не трогаем return val; });
не работает. Если из лямбды вернуть null, то метод бросает NullPointerException. Переписал так
clients.entrySet().removeIf((entry) -> { if (entry.getValue() <= currentTime) { removeClients.add(entry.getKey()); return true; } return false; });


Ответ

Синхронизируясь по одному объекту dbMonitor вы ограничиваете паралелльность вашего решения. То есть, клиенты будут "ждать" базу данных, даже если они с разным clientId. Если использовать встроенную синхронизацию в ConcurrentHashMap, то получится большая "паралленость" ActiveClientManager'а.
Но конечно же лучше проверить производительность тестами. Попробуйте создать менеджер, и вызвать методы accept, testTimeout из разных потоков.
Не претендую на абсолютную истинность решения, указал лишь на то, что бросилось в глаза.
Пример:
public class ActiveClientManager implements Consumer { private final Map clients = new ConcurrentHashMap<>(); private final PoolDataSource pds; private final long timeout;
public ActiveClientManager(PoolDataSource pds, long timeout) { this.pds = pds; this.timeout = timeout; }
// Действие клиента @Override public void accept(Integer clientID) { // Время после которого, клиент уходит в оффлайн long offlineTime = System.currentTimeMillis() + timeout; // Вставляем нового клиента, или обновляем существующего // синхронизируемся только если один и тот же clientID clients.compute(clientID, (oldVal, newVal) -> { if (oldVal == null) { try { try (Connection con = pds.getConnection()) { try (PreparedStatement stmt = con.prepareStatement("UPDATE clients SET state = 1 WHERE id = ?")) { stmt.setInt(1, clientID); stmt.executeUpdate(); } } } catch (SQLException e) { e.printStackTrace(); } } return offlineTime; }); }
// Обработка события таймера public void testTimeout() throws SQLException { long currentTime = System.currentTimeMillis(); // Сюда занесем всех клиентов, которые уже отвалились // синхронизируемся на конерктном client clients.replaceAll((client, val) -> { if (val <= currentTime) { // если время уже прошло, то сохраняем нашего клиента try (Connection con = pds.getConnection()) { try (PreparedStatement stmt = con.prepareStatement("UPDATE clients SET state = NULL WHERE id = ?")) { // блокируем добавление нового клиента stmt.setInt(1, client); stmt.executeUpdate(); } } catch (SQLException e) { e.printStackTrace(); } // и удаляем его из общего списка return null; } // иначе ничего не трогаем return val; }); } }
Update По второй реализации бросается к глаза, что Вы не определились, что делать если база не работает(или возвращает ошибки). В первом случае - accept вы собираете список исключений, и пытаетесь обновлять "хоть каких-то" клиентов, даже если база начинает "сбоить". А в втором случае - testTimeout просто логируете сообщение в консоль. На вашем месте, я бы в обоих случаях бросал RuntimeException, потому что продолжать работать при не работающей базе кажется не логично. Но это зависит от того как Вы работаете с исключениями выше по коду.
Насчет двух циклов, логично не создавать коннект к базе, если он не нужен. Но два идентичных условия проверки - лишь усложняют код. И в будущем если Вам понадобится изменить условие придется менять в двух местах. Я бы оставил создание коннекта внутри.
Так же кажется, что код по работе с базой логично вынести в два отдельных метода или даже объединить в один.
Есть ощущение, что интерфейс Consumer здесь лишний. Напрашивается интерфейс с двумя методами get(), put(). Так же из кода не ясно кто будет вызывать методtestTimeout. Кажется, что этот метод должен вызывать сам менеджер, через какой-то промежуток времени, ведь это его зона отвественности - поддержка в актуальном состоянии статусов клиентов. Тогда следует завести например Executors.newScheduledThreadPool(1), и в нем поток который будет вызывать приватный метод testTimeout.
Обновленная версия
public class ActiveClientManager implements Consumer { private final Map clients = new ConcurrentHashMap<>();; private final PoolDataSource pds; private final long timeoutMSec; private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
public ActiveClientManager(PoolDataSource pds, long timeoutMSec) throws SQLException { this.pds = pds; this.timeoutMSec = timeoutMSec; executorService.scheduleWithFixedDelay(this::testTimeout, 5 ,5, TimeUnit.MINUTES); }
private void testTimeout() { long currentTime = System.currentTimeMillis();
clients.entrySet().removeIf((entry) -> { // если время уже прошло if (entry.getValue() < currentTime) { // обновляем БД updateState(entry.getKey(), State.notactive); // удаляем этот элемент return true; } return false; }); }
private void updateState(Integer clientId, State state) { try (Connection con = pds.getConnection(); PreparedStatement stmt = con.prepareStatement("UPDATE clients SET state = " + state.getSqlState() + " WHERE id = ?");) { stmt.setInt(1, clientId); stmt.executeUpdate(); } catch (SQLException e) { throw new RuntimeException(e); } }
@Override public void accept(Integer clientID) { long offlineTime = System.currentTimeMillis() + timeoutMSec; clients.compute(clientID, (key, oldval) -> { // Если запись новая - обновляем БД if (oldval == null) { updateState(clientID, State.active); } return offlineTime; }); }
public enum State { active("1"), notactive("NULL");
private final String sqlState;
State(String sqlState) { this.sqlState = sqlState; }
public String getSqlState() { return sqlState; } } }