Страницы

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

четверг, 20 июня 2019 г.

Лимит открытых файлов Apache

Обновился на Centos 7 и на домашнем сервере вылезла проблема. На сервере установлен virtualmin. Веб сервер работает на голом апаче без nginx, но с php-fpm, при помощи которого я переключаю версии php. Это мне нужно для работы.
Через какое-то время апач падает с вот такой ошибкой:
mod_fcgid: stderr: PHP Warning: Unknown: failed to open stream: Too many open files in Unknown on line 0
Погуглил, нашел как увеличить разрешение на количество файлов, применил.
# su printforms sh-4.2$ ulimit -n 400000
Но падения не прекратились. Создал на этом виртуалхосте файл php со следующим содержимым:
Получаю в ответ 1024
Как сделать так, чтобы апач принял системные значения? Или как прописать эти лимиты в апаче? Желательно глобально. А то я постоянно новые площадки создаю или убираю.


Ответ

Создайте файл /etc/systemd/system/httpd.service.d/10-limits.conf с содержимым:
[Service] LimitNOFILE=10240
Далее примените изменения:
systemctl daemon-reload systemctl restart httpd
Действующие лимиты:
cat /proc//limits

Расширение для Chrome, работа с DOM

Ни разу не писал расширение для Хрома. Почитал немного материалы от Гугла. Не сильно помогло, тем более плохо знаю JS.
В общем, что мне нужно. А нужно простое пока действие: открываю сайт, логинюсь, нажимаю на кнопку расширение, активирую его. Расширение периодически по таймеру на этом сайте кликает на Таб в виджете, к которому привязано событие "click", которое дергает ajax запрос и получает данные с сервера и обновляет содержимое Таба. После чего, расширение должно проверить, появилось ли что-то в Табе. Таб - это вкладка в виджете. Если что-то появилось - дергает внешний url.
Как это правильно организовать? Что прописать в манифесте? Как достучаться из расширения к DOM сайта?
В принципе, через devtools кликнутьпо табу могу через: document.getElementsByClassName('tab')[0].click(), как это периодически дергать из расширения?


Ответ

Чтобы достучатся из расширения к DOM сайта, вам нужен контент скрипт (вся работа с DOM ведется там). В манифесте указываете, в какие страницы его загружать, примерно так: manifest.json:
{ /* тут бла-бла-бла имя автора версия и прочие тырыпыры, https://developer.chrome.com/extensions/manifest тут все достаточно подробно описано */ "permissions": [ "http://ваш.сайт.цель/*" ], "content_scripts":[ { "matches": [ "http://ваш.сайт.цель/*" //https://developer.chrome.com/extensions/content_scripts#match-patterns-globs ], "js": ["content_script.js"] } ] }
Чтобы активировать расширение, нажав на кнопку расширение, вам нужен popup: в манифест добавляем
"browser_action":{ "default_popup":"popup.html" },
в теле popup.html напишите код, который будет сохранять куда-либо факт того, что приложение активировано. Тут масса вариантов, насколько я понял вашу задачу, будет достаточно просто посылать сообщение в content_script, примерно так:
popup.html:
Hello Chrome World:)
popup.js
chrome.runtime.sendMessage('start');
content_script.js:
chrome.runtime.onMessage.addListener(function(request,sender,callback){ if(request=='start'){ setInterval(function(){ document.getElementsByClassName('tab')[0].click() },228); } });
Но вы можете сделать это массой других способов, например воспользовавшись chrome.storage.local или background скриптом, который будет работать, пока вы не закроете браузер, удалите или не отключите расширение.

Фильтр в Django по дате

Как сделать, чтобы выводились по дате сначала новые записи, потом более старые. Сейчас выводится наоборот сначала старые
views.py:
from django.shortcuts import render, get_object_or_404 from post.models import Post from django.utils import timezone
def home(request): posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') return render(request, 'frontend/home.html', {'posts': posts})
Модель:
class Post(models.Model): class Meta: db_table = "post"
author = models.ForeignKey('auth.User', default='user') title = models.CharField(max_length=200) text_preview = models.TextField(max_length=100, default='') image_preview = models.ImageField(upload_to = 'img/', default='') text = models.TextField(default='') created_date = models.DateTimeField(default=timezone.now) published_date = models.DateTimeField(blank=True, null=True)
def publish(self): self.published_date = timezone.now() self.save()
def __unicode__(self): return self.title


Ответ

Для того, чтобы вывести записи по убыванию, надо в order_by перед названием поля поставить "-".
def home(request): posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('-published_date') return render(request, 'frontend/home.html', {'posts': posts})

переместить файлы из одного репозитория в другой с историей коммитов

Здравствуйте. У меня есть два репозитория
Checker.rep
1Ch.file 2Ch.file 3Ch.file
Main.rep
Checker.folder
Подскажите как переместить файлы из репозитория Checker.rep в папку Checker.folder так, чтобы история коммитов сохранилась и можно было удалить оставшийся пустой репозиторий Checker?


Ответ

Поскольку это две отдельных несвязанных истории, чтобы их связать, придётся делать слияние. Сбивает с толку тот факт, что ветки в разных репозиториях, и как слияние делать, неясно... это поправимо, хотя и не совсем так, как по ссылке. Один репозиторий можно затянуть в другой.
Просто делать pull из другого репозитория не стоит, потому что в этом случае файлы из корня одного репозитория попадут в корень другого, а цель немножко другая. Поэтому вместо pull сделаем то, из чего он состоит: fetch+merge
В Main.rep
git remote add checker путь/к/Checker.rep # указать источник git fetch checker # только скачать (!) коммиты # warning: no common commits # <- ну, это ожидаемо # remote: Counting objects: 5, done. # remote: Compressing objects: 100% (4/4), done. # remote: Total 5 (delta 1), reused 0 (delta 0) # Unpacking objects: 100% (5/5), done. # From путь/к/Checker.rep # * [new branch] master -> checker/master git merge checker/master --no-commit
Интерес представляет флаг --no-commit (ради этого и затевался обход вокруг pull), который после завершения процедуры слияния остановит Git, чтобы можно было поправить результаты. Самое время закинуть прилетевшие при слиянии файлы в нужную папку:
git mv *Ch.file Checker.folder
Вот вроде и всё, достигнуто желаемое состояние.
git commit
Готово.

Django. Передача параметров из шаблона c формой в представление и запись в БД

Нужно организовать передачу в функцию данных одного из полей формы(для записи в БД) и дополнительных элементов(присутствуют на странице шаблона) user.id, status.id . Сейчас в функцию передается только product.id, при добавлении дополнительных элементов в , при переходе на страницу с формой выдает:
Reverse for 'zakaz' with arguments '(1, 2)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['(?P[0-9]+)/zakaz/$']
как настроить передачу нужных параметров в представление и последующую запись их в БД в нужные столбцы?
models.py
class Zakaz(models.Model): user = models.ForeignKey(User) product = models.ForeignKey("product", Product) status = models.ForeignKey("status", Status) suggestions = models.TextField("пожелания", max_length=1000)
forms.py
class ZakazForm(forms.ModelForm): class Meta: model = Zakaz fields = ['suggestions']
views.py
def detail(request, pk): product = get_object_or_404(Product, pk=pk) form = ZakazForm context = {'product': product, 'form': form} return render(request, 'main/detail.html', context)
def zakaz(request, pk): if request.method == 'POST': form = ZakazForm(request.POST) if form.is_valid(): // Запись всего в БД return HttpResponseRedirect('/thanks/') else: product = get_object_or_404(Product, pk=pk) form = ZakazForm context = {'product': product, 'form': form} return render(request, 'main/detail.html', context)
urls.py
urlpatterns = [ url(r'^$', views.IndexView.as_view(), name='index'), url(r'^(?P[0-9]+)/$', views.detail, name='detail'), url(r'^(?P[0-9]+)/zakaz/$', views.zakaz, name="zakaz"), url(r'^thanks/$', views.thanks, name="thanks"), ]
detail.html

{% csrf_token %}
{{ field.label_tag }}
{{ form }}


Ответ

Попробуйте передавать в url именованный аргумент:
{% url 'main:zakaz' pk=product.id %}

Запрет выдачи DHCP-сервером IP-адреса клиенту вне dhcpd.conf

Идея в том, чтобы запретить клиентам получать по DHCP адрес, если этот клиент (хост) не описан в dhcpd.conf.
Таковой штатной функциональности в dhcp не обнаружил (возможно, плохо смотрел), а городить костыли как-то не хочется.


Ответ

реализации dhcpd бывают разные. поэтому уточните в документации к вашему dhcpd, поддерживаются ли в нём директивы deny и allow
пример можно увидеть, например, здесь
subnet 10.0.0.0 netmask 255.255.255.0 { option routers 10.0.0.254;
# Unknown clients get this pool. pool { option domain-name-servers bogus.example.com; max-lease-time 300; range 10.0.0.200 10.0.0.253; allow unknown-clients; }
# Known clients get this pool. pool { option domain-name-servers ns1.example.com, ns2.example.com; max-lease-time 28800; range 10.0.0.5 10.0.0.199; deny unknown-clients; } }

Скрыть выпадающее меню при клике куда угодно JQuery

Хочу сделать меню, которое открывается по нажатию на кнопку и закрывается при клике по любой части экрана. Проблема в том, что меню закрывается при клике куда угодно, кроме кнопки открывания. По моей задумке, после открытия меню класс у кнопки убирается и она должна становиться неактивна, а значит становится такой же как и любая часть документа, но этого почему-то не происходит. В чем моя ошибка?
$(document).ready(function() { $(hidden).slideUp();
$('.switch').click(function() { $(hidden).slideDown(300); $('#drop-but').removeClass('switch'); return false; });
$(document).click(function() { $(hidden).slideUp(300); $('#drop-but').addClass('switch'); }); });


Ответ

Как вариант:
$(function() { $('.menu-wrap').on('click', function() { var $this = $(this); if ($this.hasClass('active')) { $this.removeClass('active'); $(document).off('click.menu'); } else { $this.addClass('active'); $(document).on('click.menu', function(e) { if ($(e.target).closest('.menu-wrap').length === 0) { $('.menu-wrap').removeClass('active'); $(document).off('click.menu'); } }); } }); }); .menu-wrap { position: relative; width: 100px; } .menu-title { width: 100%; border: 1px solid black; cursor: pointer; transition: all .5s; } .menu-wrap.active .menu { visibility: visible; opacity: 1; } .menu { border: 1px solid black; border-top: none; width: 100%; visibility: hidden; opacity: 0; transition: all .5s; } ul { list-style-type: none; margin: 0; padding: 0; } li:hover { cursor: pointer; background: #eee; }


Как вызвать метод объявленный из абстрактного класса в инициализации этого класса

Есть абстрактный класс, который имеет метод public void SomeMethod() {} Как при объявлении объекта класса вызвать этот метод из переопределенного?
private static void AbstrClassInit() { Dialog abstrClass = null; // Если тут final, то (1), если нет (2) abstrClass = new AbstrClass() { //(1) Cannot assign a value to final variable @Override public void EscapeAction() { abstrClass.SomeMethod(); //(2) Variable 'abstrClass' is accesed from within inner class, needs to be declared final }; }


Ответ

Вы изначально инициализируете переменную значением null после этого, если он финальная, её нельзя переинициализировать. Таким образом вам надо сразу инициализировать переменную экземпляром класса и сделать её финальной для доступа из внутреннего класса.
При этом вы вообще пытаетесь при определении класса вызвать метод его экземпляра... Это вы что-то не то делаете. Вам надо просто вызвать метод через this, коий и является ссылкой на экземпляр вашего класса.
private static void AbstrClassInit() { final Dialog abstrClass = new AbstrClass() { @Override public void EscapeAction() { this.SomeMethod(); }; }

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

Привет. Есть два приложения на C# - служба (windows service, для службы был указан Account LocalSystem) и клиентское приложение(обычное windows приложение, в данном случае консольное), которые обмениваются информацией по именованным каналам (Named Pipes). Проблема в том, что клиентское приложение может подключиться к службе по именованному каналу только с правами администратора.
Нашёл в сети решение, в котором предлагается назначить серверному именованному каналу PipeSecurity, содержащий один или более PipeAccessRule. После применения этого подхода серверное приложение падает с исключением System.UnauthorizedAccessException. Подскажите, как по именованному каналу осуществить подключение к службе клиентского приложения, которое запущено без прав админа? Делаю так:
Windows Service
protected override void OnStart(string[] args) { new Thread(() => { while (true) { using (var pipe = new NamedPipeServerStream("test", PipeDirection.InOut, 1, PipeTransmissionMode.Byte)) { var ps = new PipeSecurity(); ps.AddAccessRule(new PipeAccessRule(WindowsIdentity.GetCurrent().Name, PipeAccessRights.FullControl, AccessControlType.Allow)); pipe.SetAccessControl(ps);
pipe.WaitForConnection(); int x = pipe.ReadByte(); pipe.WriteByte((byte)(x + 1)); } } }) { IsBackground = true }.Start(); }
Клиент:
using (var pipe = new NamedPipeClientStream(".", "test", PipeDirection.InOut)) { pipe.Connect(); pipe.WriteByte(100); int x = pipe.ReadByte(); Console.WriteLine(x); }
Пробовал также в коде службы WindowsIdentity.GetCurrent().Name менять на "Everyone", но в этом случае исключение System.Security.Principal.IdentityNotMappedException.


Ответ

Попробуйте такую реализацию:
new Thread(() => { var ps = new PipeSecurity();
// себе разрешаем все ps.AddAccessRule( new PipeAccessRule( WindowsIdentity.GetCurrent().Owner, PipeAccessRights.FullControl, AccessControlType.Allow));
// остальным только чтение/запись в пайп ps.AddAccessRule( new PipeAccessRule( new SecurityIdentifier(WellKnownSidType.WorldSid, null), PipeAccessRights.ReadWrite, AccessControlType.Allow));
while (true) { // параметры безопасности передаем в конструктор, а не в SetAccessControl using (var pipe = new NamedPipeServerStream("test", PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.None, 0, 0, ps)) { pipe.WaitForConnection(); int x = pipe.ReadByte(); pipe.WriteByte((byte)(x + 1)); } } }) { IsBackground = true }.Start();

Создать программно bmp файл

Смотрел решение данной проблемы на msdn и тут : C++ How to create a bitmap file
Создает файл с расширением .bmp но при этом в описании ничего нету, файл пишет что поврежден. заголовок читал, смотрел, вроде то. пытался скопировать из bmp в bmp, если полностью скопировать bmpFileHeader и bmpInfoHeader то работает. Также пробовал делать еще некоторые манипуляции, перевернуть отразить. Похоже что я что то не так делаю с заголовками
BITMAPFILEHEADER bmpFileHeader = { 0 }; BITMAPINFOHEADER bmpInfoHeader = { 0 }; RGBQUAD RGBcolor; for (size_t i = 0; i < height*width; ++i) image[i].reserved = 0; bmpFileHeader.bfType = 0x4d42; bmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER); bmpInfoHeader.biWidth = width; bmpInfoHeader.biHeight = height; bmpInfoHeader.biSizeImage = (DWORD)(bmpInfoHeader.biWidth * bmpInfoHeader.biHeight); bmpInfoHeader.biPlanes = 1; bmpInfoHeader.biBitCount = 8; bmpInfoHeader.biCompression = BI_RGB; bmpInfoHeader.biXPelsPerMeter = bmpInfoHeader.biYPelsPerMeter = 2000;
bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER)+bmpInfoHeader.biSize + bmpInfoHeader.biSizeImage; bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + bmpInfoHeader.biSize + sizeof(RGBQUAD); for (size_t i = 0; i < height * width; ++i){ fwrite(&image[i], sizeof(RGBQUAD), 1, output); }
typedef struct RGB{ BYTE rgbtBlue; BYTE rgbtGreen; BYTE rgbtRed; BYTE reserved; };


Ответ

bmpFileHeader.bfSize -- поле заполнено неверно, должно быть: bmpFileHeader.bfSize = sizeof(BITMAPINFOHEADER);
bmpFileHeader.bfOffBits -- здесь вы оставляете место под 256 записей палитры -- непонятно зачем, потому что очевидно палитра вам тут не нужна и вы её точто не заполняете, а сразу пишете пиксели.
Также обратите внимание, что изображение в bmp -- перевёрнутое, т.е. нижняя строка пикселов идёт первой, затем та что над ней итд.
Вообще, нужно внимательно читать описание каждого поля. По вашему коду видно, что многое вы упустили. Вот описание структуры на русском: http://www.vsokovikov.narod.ru/New_MSDN_API/Bitmaps/str_bitmapinfoheader.htm
В качестве примера работающего кода могу дать свой: https://github.com/nzeemin/ukncbtl/blob/master/util/BitmapFile.cpp -- функция BmpFile_SaveScreenshot() в самом начале файла.
Проверьте поле biBitCount -- сейчас у вас оно показывает что цвет 8-битный, а заливаете вы 32-битные пиксели.

Обтекание текста под углом


Как сделать такое обтекание текста под углом?


Ответ

https://css-tricks.com/almanac/properties/s/shape-outside/
.block{ overflow: hidden; margin: 10px; padding: 15px; } .pict{ float:left; width:100px; height:150px; margin:10px; background-color: #ccc; -webkit-shape-outside: polygon(100% 50%, 0 0, 0 100%); shape-outside: polygon(100% 50%, 0 0, 0 100%); -webkit-clip-path: polygon(100% 50%, 0 0, 0 100%); clip-path: polygon(100% 50%, 0 0, 0 100%); -webkit-shape-margin: 10px; shape-margin: 10px; }

text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text

или
.block{ overflow: hidden; margin: 10px; padding: 15px; } .pict{ float:left; width:100px; height:150px; margin:10px; background-color: #ccc; -webkit-shape-outside: polygon(0 0, 100% 50%, 100% 100%, 0% 100%); shape-outside: polygon(0 0, 100% 50%, 100% 100%, 0% 100%); -webkit-clip-path: polygon(0 0, 100% 50%, 100% 100%, 0% 100%); clip-path: polygon(0 0, 100% 50%, 100% 100%, 0% 100%); -webkit-shape-margin: 10px; shape-margin: 10px; }
text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text

Свой toolbar для каждого Fragment'a

Использую несколько фрагментов, для которых есть отдельный тулбар. При добавлении тулбара подсвечивается в студии ошибка "activity.getSupportActionBar.setTitle() may produce java.nullpointerexeption". При этом фрагмент грузится, но все действия залипают, на другие фрагменты он не переходит. Прошу подсказать в чем ошибка?
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_three,container,false); Toolbar profile_toolbar = (Toolbar)view.findViewById(R.id.profile_toolbar); AppCompatActivity activity = (AppCompatActivity)getActivity(); activity.getSupportActionBar().setTitle("dgdfg"); return view; }
UPD. Ошибка крылась в использовании FragmentTabHost, почему-то вид с фрагментом залипал на фрагменте с использование тулбара. Пришлось заменить FragmentTabHost на TabHost


Ответ

Это не ошибка, а предупреждение Android Studio т.к. при определенных условиях метод getSupportActionBar() может вернуть null и вот тогда уже случится NullPointerException в вашем приложении. Чтобы это исключить, достаточно выполнить проверку на null. Тогда и студия перестанет пугать этим сообщением.
ActionBar actionBar = activity.getSupportActionBar(); if(actionBar!= null) { //какой то код }
Из-за этого скорей всего и залипают ваши фрагменты, т.к. вы только нашли ToolBar, но не установили его, потому getSupportActionBar() возвращает null. Попробуйте сделать так:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_three,container,false); Toolbar profile_toolbar = (Toolbar)view.findViewById(R.id.profile_toolbar); AppCompatActivity activity = (AppCompatActivity)getActivity(); activity.setSupportActionBar(profile_toolbar); ActionBar actionBar = activity.getSupportActionBar(); if(actionBar!= null) { actionBar.setTitle("dgdfg"); } return view; }

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

Возможно ли анализировать трафик (приходящие пакеты) на уровне Java?
Если возможно, то как и правильно ли так делать?


Ответ

Я бы порекомендовал PCAP https://ru.wikipedia.org/wiki/Pcap Используй jNetPcap (http://jnetpcap.com/) PCAP является стандартным решением для собственных таких программ

Как получить прямую ссылку на изображение ВКонакте по его ID?

У меня есть ссылка на запись с фотографией — фото
Как получить прямую ссылку на изображение вида https://pp.vk.me/c320525/v320525404/5502/wDguXeHdmZk.jpg для загрузки Universal Image Loader'ом?

P.S. В VK Api я не нашел нужного метода для получения ссылки на фото по его id (213737404_316668269), поэтому идеи, кроме как получать ссылку напрямую — нет.


Ответ

В доках говорится, что надо использовать метод photos.getById
https://vk.com/dev/photos.getById?params[photos]=213737404_316668269¶ms[extended]=1¶ms[photo_sizes]=0¶ms[v]=5.52

Т.е. итоговый запрос такой:
https://api.vk.com/method/photos.getById?photos=213737404_316668269
Ответ такой:
{"response":[{"pid":316668269,"aid":-6,"owner_id":213737404,"src":"http:\/\/cs320525.vk.me\/v320525404\/5501\/Js1OGe3cJMs.jpg","src_big":"http:\/\/cs320525.vk.me\/v320525404\/5502\/wDguXeHdmZk.jpg","src_small":"http:\/\/cs320525.vk.me\/v320525404\/5500\/FfVY13pbe3I.jpg","width":600,"height":600,"text":"","created":1388256629,"post_id":972}]}

Компиляция cpp-файла с файлом предкомпиллированных заголовков расположенного в другой папке

Как решить вопрос с ситуацией заданной в теме?
У меня есть проект на C++ структура, котого выглядит так:
../parse/ ../../export.cpp ../../import.cpp ../../и др. файлы ../precomp.hpp ../precomp.cpp
В текущей ситуации получаю вполне логичную ошибку:
\parse\export.cpp(1): warning C4627: '#include "../precomp.hpp"': skipped when looking for precompiled header use Add directive to 'precomp.hpp' or rebuild precompiled header
Мне бы хотелось избежать ситуации с переносом файлов из папки parse/ на уровень выше где расположен файл precomp.hpp, но как иначе пока не вижу способа.
Так есть ли способ скомпиллировать проект с текущей структурой с предкомпиллированными заголовками, когда файл precomp.hpp в одной, а export.cpp в другой?


Ответ

В файле \parse\export.cpp инклюдьте без указания пути:
#include "precomp.hpp"
Не важно, что путь не существует, главное чтобы совпадало написание precomp.hpp с тем, которое указано в настройке Precompiled Header File проекта/файла.

Symfony. Не удается подключить CSS/JS

Установил Symfony 3.0.4, в каталоге web разместил папку css с файлами стилей. В base.html.twig прописал:
{% block stylesheets %} {% endblock %}
Но когда перехожу обновляю страницу, в консоле пишет что мой app.css 404 not found. Я перечитал всю документацию, посмотрел кучу видео и прочитал много статей из неофициальных источников и этот способ работает везде! но только не у меня. Для убедительности установил symfony-demo проект и там тоже не работает, причем изначально там прописан такой же код что я написал выше. Может что-то не так с веб-сервером? я уже не знаю что делать. Исходников никаких нет, проделываю всё в новом (чистом) проекте. Ещё пробовал чистить кеш - не помогло.
Вот видео о том как подключить, у меня не работает этот способ. https://knpuniversity.com/screencast/symfony/layout-assets


Ответ

Когда добавлял virtualhost в apache, в качестве DocumentRoot указывал ../web/app_dev.php, а нужно было всю папку web, без файла.

SSH-проксирование

В текущей инфраструктуре существует docker-контейнер с gitlab, к которому надо прокинуть ssh-доступ из машины-хоста, т.е. предполагается примерно такое взаимодействие:
ssh root@host: обычный вход ssh git@host: прием произвольного сертификата, затем проксирование подключения к git@localhost:10022 с тем сертификатом, с которым обратился клиент. Для клиента это должно выглядеть как обычное подключение.
Как организовать подобную архитектуру?


Ответ

Представленный метод не совсем соответствует вашим требованиям, но другим способом пробросить ключ, по-видимому, нельзя. Подключение будет перенаправлено на второй сервис, аутентификация на нем пройдет автоматически по тому же ключу, но перед подключением пользователю придется произвести дополнительные действия.
На стороне сервера
В файле /etc/ssh/sshd_config добавляем следующие строки, которые осуществляют немедленное переподключение ко второму ssh-сервису сразу после логина пользователя git (на других пользователей не действует):
Match User git ForceCommand ssh git@localhost -p 10022
На сервере host должен существовать пользователь git с заполненным ~/.ssh/authorized_keys
На стороне пользователя
Необходимо перед подключением у пользователя запустить программу ssh-agent (командой eval `ssh-agent`) и добавить в нее ключ командой ssh-add. Затем пользователь подключается к вашему серверу командой
ssh -A username@host
Параметр -А включает проброс ключа, username - это root или git в вашем случае. Пока ssh-agent висит в памяти, проброс будет работать. Проброс на второй сервис выполнится прозрачно и незаметно для пользователя.
Также можно поправить конфиг /etc/ssh/ssh_config у пользователя, чтобы каждый раз не указывать ключ -A
Host * ForwardAgent yes

Консоль/Терминал в Андроид

Android основана на Linux и принадлежит к их семейству. Но существует ли в них самый главный компонент, на самом деле не такой уж и главный, а именно – терминал?
То есть могу ли я обратиться непосредственно из самой ОС, которая предоставлена пользователю, к командной строке, и, допустим, пуститься в далекие путешествия как на обычной *nix системе?


Ответ

Конечно, выбирай какой нравится Но учти, что пользователю доступно не так уж и много. Для полного доступа необходимы root-права на устройство.
Самым популярным способом получения root прав считаю Framaroot. Поддерживает большинство устройств, проверь своё
Важно!!!
Получение root прав на устройстве снимает устройство с гарантии
Так что на свой страх и риск.

Проблемы с динамической памятью

В приведённом ниже коде не получается использовать динамическую память.
Я выделяю указателю динамическую память под max элементов , далее пытаюсь записать в часть памяти несколько значений для дальнейшего сравнения. Например
*parr = 2; *(parr + 1) = 3; *(parr + 2) = 5;
Но указатель не переходит выше по элементам , а пишет всё в один (точнее переписывает значение в этом же элементе)
long* parry(nullptr); // пустой указатель. long trial = 5; // кандидат на простое число. int count = 3; // кол-во простых чисел (объявленных) int found = 0; // признак обнаружения простого числа. int max2 = 0; // определяем кол-во простых чисел
cout << "enter the numbers of digits: "; cin >> max2;
parry = new long[max2]; // выделяю память под max2 элементов. // // собственно проблема на следующей строке. *parry = 2; // пишу в первый элемент 2. *(parry + 1) = 3; // пишу во второй элемент 3. *(parry + 2) = 5; // пишу в 3-ий 5.
do { trial += 2; found = 0;
for (int i = 0; i < count; ++i) { found = (trial % *(parry + i)) == 0;
if (found) break; } if(found == 0) *(parry + count++) = found;
} while (count < max2);
for (int i = 0; i < max2; ++i) { if (i % 5 == 0) cout << endl; cout << setw(6) << *(parry + i); } delete[] parry; parry = nullptr; cout << endl;
return 0; }


Ответ

Измените код
if(found == 0) *(parry + count++) = found;
на следующий
if(found == 0) *(parry + count++) = trial;
У вас происходит заполнение нулями и при следующих итерациях идёт деление на ноль вот тут
found = (trial % *(parry + i)) == 0;
Работающий пример

Сортировка результатов запроса по заданной в массиве последовательности

Как можно получить вывод записей из базы данных в той последовательности в которой передано id записей (у меня записи постоянно выводятся последовательно 1 - 5).
$connect= mysql_connect("localhost", "testing", "testing"); $select = mysql_select_db("testing", $connect); mysql_query("SET NAMES utf8");
$id = "5,2,1,4,3"; $result = mysql_query("SELECT * FROM products WHERE id IN ($id)");
while ($data = mysql_fetch_row($result)) { echo "

$data[0] ........."; echo "$data[2]

"; }


Ответ

Для этого можно воспользоваться MySQL-функцией FIELD(), которая возвращает позицию вхождения первого аргумента в список, который задается оставшимися аргументами. В качестве первого параметра передавайте значение из поля id, а в качестве остальных аргументов используйте значения из списка $id. Результат выполнения функции передавайте ключевому слову ORDER BY, осуществляющему сортировку результатов выборки
$connect= mysql_connect("localhost", "testing", "testing"); $select = mysql_select_db("testing", $connect); mysql_query("SET NAMES utf8");
$id = "5,2,1,4,3"; $result = mysql_query( "SELECT * FROM products WHERE id IN ($id) ORDER BY FIELD(id, $id)" );
while ($data = mysql_fetch_row($result)) { echo "

$data[0] ........."; echo "$data[2]

"; }

Проверка автризации в urls.py

Хочу полностью закрыть сайт для не авторизованных.. Подскажите что не так?
Django==1.9.6 urls.py
from django.conf.urls import url from django.contrib import admin from . import views
from django.contrib.auth.models import User
if User.is_authenticated: urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^$', views.home_page), ] else: urlpatterns = [ url(r'^admin/', admin.site.urls), ]


Ответ

Чтобы "пометить" какой-то url или группу url'ов, как требующие авторизации, можно воспользоваться декоратором:
urls.py
from django.contrib.auth.decorators import login_required
urlpatterns = [ ... url(r"^select2/fields/auto.json$", login_required(AutoResponseView.as_view()), name="django_select2-json"), ... ]
Если хочется закрыть весь сайт от неавторизованных пользователей, то стоит использовать middleware. Например, таким:
middleware.py
from django.http import HttpResponseRedirect from django.conf import settings from re import compile
EXEMPT_URLS = [compile(settings.LOGIN_URL.lstrip('/'))] if hasattr(settings, 'LOGIN_EXEMPT_URLS'): EXEMPT_URLS += [compile(expr) for expr in settings.LOGIN_EXEMPT_URLS]
class LoginRequiredMiddleware: if not request.user.is_authenticated(): path = request.path_info.lstrip('/') if not any(m.match(path) for m in EXEMPT_URLS): return HttpResponseRedirect(settings.LOGIN_URL)
Его надо прописать в MIDDLEWARE_CLASSES:
settings.py
MIDDLEWARE_CLASSES = [ ... appname.middleware.LoginRequiredMiddleware, ... ]

Где я ошибаюсь в алгоритме классификации текстов?

Здравствуйте. У меня такая проблема. В связи скудностью информации по классификации текстовых сообщений на русском языке возникли некоторые вопросы и не до конца понятен четкий алгоритм действий.
Дано - csv файл с запросами (10000), которые надо распределить на категории. Я так понял такой алгоритм:
Берём файл и проводим нормализацию - удаляем стоп-слова и знаки препинания, приводим все слова к единой форме (или правильно сказать в начальную форму, т.е. выполняется стемминг). Потом делим всю выборку на тестовую и обучающую (30 к 70). Получается вручную размечаем корпус по категориям? Или можно использовать TF-IDF для выделения часто встречающихся слов? Переводим слова в векторную форму. Тут тоже вопрос - как лучше? Использовать Bag of Words? Получается для каждого запроса строить отдельно вектор с встречающимся в них словах или делать сразу для всей категории (или возможно для всей выборки)? То есть на выходе мы должны получить несколько векторов или один большой вектор (с часто входящими словами?) для целой категории? Подаем полученный/ые вектор/а на вход какому-нибудь из алгоритмов классификации. Обучаем его. Берем запрос из тестовой выборки, так же приводим его в нормальную форму и подаем на вход алгоритма и смотрим ответ.
Вроде как-то так. И сразу последний вопрос - чтобы по 10 раз не обучать классификатор и не хранить все в памяти можно как-нибудь (например, если мы возьмем нейронную сеть) записывать веса и при загрузке просто распределять уже их и готово или каждый раз придется проходить обучение? Заранее всем спасибо


Ответ

1) Классификация звучит как-то размыто. Какие конкретно классы нужны? Вариантов масса - спам\неспам, извлечение тематики и т.д. Можно даже предоставить пару примеров исходных текстов.
2) Нормализация и стемминг алгоритмы похожие, но все же разные. Нормализация - приведение слова к единственному числу, именительному падежу, инфинитив для глагола, настоящее время и т.д. Стемминг - крайне грубая операция, которая просто отсекает суффиксы и окончания. Зато быстрая. Ну и как правильно было отмечено, перед нормализацией удаляются стоп-слова - предлоги, междометия всякие. Может даже имена собственные - даже на этом шаге есть над чем поразмышлять.
3) Если изначально нет обучающей выборки с размеченными классами, то задача резко усложняется. TF-IDF - всего лишь способ представить слова в виде векторов - он не сможет автоматически извлечь какие-то слова, которые характеризовали бы предложение. У TF-IDF нет такого параметра, как "важность", "вес" слова. (Кстати, выходом частотной модели векторизации будет множество векторов - по одному вектору на каждое уникальное слово). Есть только частота, а я бы поостерегся утверждать, что какое-то одно слово характеризует весь текст или предложение, основываясь только на частоте. Таким образом, если нет обучающей выборки, то это тупик. И нужно смотреть на другие алгоритмы - LDA, LSI - они способны разбить множество входных текстов на категории, на "темы", основываясь на содержании этих текстов. Неизвестен патентный статус. Меня результаты работы этих алгоритмов не впечатлили.
4) Если есть обучающая выборка, то все также не очень просто. Нельзя просто так взять и обучить классификатор на входных данных переменной длины - в разных документах или предложениях разное количество векторов. А все классичиеские классификаторы работают с входным вектором одинаковой длины. Выходов здесь можно придумать также массу - интерполировать недостающие значения, заполнять пустышками, попытаться отсеивать незначащие признаки.
Таким образом, готового алгоритма в виде "скормили" массив документов и все сделалось хорошо не существует. Наиболее близки LDA, LSI. А строить гипотезы можно очень долго, осбенно, если задача толком неясна.
На чем реализовывать? Так как метка языка не была указана осммелюсь посоветовать писать это все на python. Уже написаны прекрасные библиотеки для всего, чего угодно. gensim, NLTK - для работы с текстом; skikit-learn, numpy, scipy, FANN, PyBrain, Theano - для работы с числами; pymorhy2 - для нормализации русского текста, но нормализация проводится без контекста (то есть не получится отличить "сталь" от "стать" в слове "стали").

Как указать значения по умолчанию при запуске клиента mysql?

как в unix-подобной операционной системе задать значения по умолчанию для имени хоста, базы данных, пользователя, пароля и тому полобного?
чтобы каждый раз не указывать одно и то же типа:
$ mysql -h хост -u пользователь -pпароль база-данных
а просто запускать:
$ mysql


Ответ

в документации указано местоположение файла, который прочитывается клиентом mysql при запуске:
~/.my.cnf
в нём можно указать все необходимые значения по умолчанию (конечно, их можно при необходимости переопределить из командной строки) в секции [client]
[client] host=хост database=база-данных user=пользователь password=пароль # и другие параметры для клиента mysql

для пущей безопасности имеет смысл сделать файл доступным только самому пользователю:
$ chmod go= ~/.my.cnf

кстати, этой файл учитывается и при запуске всех остальных программ из пакета mysql-client: mysqldump, mysqladmin, mysqlcheck и т.д. и т.п.

Что означает p в командной строке Ruby

Есть такая строчка:
ruby -e "p 'hello world!'"
Что означает p в Ruby? Какое полное название p?


Ответ

Метод p() содержится в модуле ядра Kernel и выводит в стандартный поток с новой строки результат вызова obj.inspect переданного ему объекта.
То есть в данном случае он берет объект 'hello world!', вызывает его метод inspect который вернет строковое представление(такое же 'hello world!') и выводит его с новой строки в стандартный вывод.

Android. Создание папки в корне SD

Необходимо создать папку в корне SD карты. Android API 21+.
В манифесте прописано:

Код:
private boolean isExistDir() { File dir = new File(Environment.getExternalStorageDirectory().getPath() + File.separator + "myDir");
if (dir.exists()) return true; if (dir.mkdirs()) return true; return false; }
Проверка на наличие SD (Возвращает true):
public boolean isExternalStorageWritable() { String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { return true; } return false; }
Но при вызове mkdirs() получаю false. Папка не создается. Как создать папку?


Ответ

Нашел решение совершенно случайно.

Почему не догадался до этого сразу:
Причина 1: Нагуглил штук 5-10 похожих вопросов, везде советовали указывать только "WRITE_EXTERNAL_STORAG".
Причина 2: Я искренне думал, что права на запись подразумевают права на чтение. Т.е. если разрешено только READ, то WRITE запрещено. Но! Если разрешено WRITE, то и READ пожалуйста.
Остается вопрос, почему не работало без "READ_EXTERNAL_STORAGE". Но думаю что это особенность API 21+.

Как подключаться по sshfs к хранилищу

Есть сервер с CentOS 6.4 и удаленное sftp-хранилище (без Линукса) Подключаюсь к нему командой:
sshfs пользователь@адрес: /var/spool/asterisk/ftpserver -o allow_other,reconnect,ServerAliveInterval=30,uid=1000,gid=1000,umask=000,nonempty
Потом надо вводить пароль. Как можно подключаться автоматически, не вводя вручную пароль? Например в curlftpfs есть такая функция:
-o user=юзер:пароль
Но curlftpfs показался мне очень медленным.
Пробовал скопировать rsa ключ на хранилище командой:
ssh-copy-id -i ~/.ssh/id_rsa.pub '-p 22 юзер@адрес'
Но выходит такая ошибка:
exec request failed on channel 0


Ответ

$ ssh-copy-id -i ~/.ssh/id_rsa.pub '-p 22 юзер@адрес' exec request failed on channel 0
вполне логично, если позволяют только sftp
если тамошний ssh-сервер вообще позволяет использовать ключи, попробуйте добавить их вручную:
примонтируйте домашний каталог этого пользователя куда-нибудь в пустой каталог:
$ sshfs пользователь@адрес: /локальный/пустой/каталог создайте в нём каталог .ssh
$ mkdir -p /локальный/пустой/каталог/.ssh добавьте в файл authorized_keys в этом каталоге ваш публичный ключ:
$ cat ~/.ssh/id_rsa.pub | tee -a /локальный/пустой/каталог/.ssh/authorized_keys сделайте каталог .ssh и его содержимое недоступным другим пользователям:
$ chmod -R go= /локальный/пустой/каталог/.ssh отмонтируйте домашний каталог:
$ fusermount -u /локальный/пустой/каталог
теперь попробуйте перемонтировать то, что вам требуется.
если всё равно запросит пароль, то, скорее всего, тамошний ssh-сервер либо вообще не поддерживает авторизацию по ключу, либо она запрещена (для данного пользователя).
тогда можно попробовать передать пароль через stdin. согласно man sshfs, программа должна понимать опцию password_stdin
$ echo пароль | sshfs -o password_stdin,другие-опции ...

Деструктурирование объекта. Ликбез

Задача: Лаконично (используя деструктуризацию), "разбить" передаваемый в функцию-конструктор объект на переменные свойства для новых экземпляров. Иными словами, почему нижеприведенный пример кода неправильный?
class Menu { constructor(options = {}) { { title: this.title = 'Empty' } = options; // (*) } }
const menu = new Menu();
К примеру, если бы строка (*) была такой: let {title: t = 'Empty'} = options;, то ошибки не будет, однако, это не избавить от писанины длинной вереницы присваиваний, наподобие: this.title = options.title || 'Empty' //...


Ответ

Проблема была в том, что в инструкции: {title: this.title = 'Empty'} = options; интерпретатор левую часть воспринимает, как блок инструкций, и соответсвенно не может произвести операцию присваивания. Наверное, это тонкий момент, но в основном потоке кода, деструктуризация должна являться частью выражения, например, let {title: t = 'Empty'} = options; В том случае, если переменные уже объявлены выше, или как в этом случае, идёт обращение к свойствам объекта, можно попробовать так:
function Menu(options = {}) { ({title: this.title = 'Empty'} = options); // (*) }
const menu = new Menu();
Теперь строка (*) заключена в круглые скобки, а фигурные интерпретируются так, как и было задумано.

Как в TypeScript указать массив классов?

Например у меня есть класс Module и от него будут наследовать много классов. Например модуль User или модуль Session, и я хочу хранить все эти классы в одном месте.
class User extends Module {
}
api.addModule(User)
как мне описать тип аргумента принимаемый функцией addModule?
addModule (moduleClass:Function){ this.modules[moduleClass.name] = moduleClass }
moduleClass:Function??? фанкшен работает, но мне нужны не любые функции а именно классы, да еще и унаследованные от Module
более того я хочу создать функцию addModules
api.addModules([User, Session])
чтобы можно было принимать массив классов =) подскажите как такой параметр описать в тайпскрипте? чтобы как бы не инстанс класса, а именно сам класс или его классы наследники.


Ответ

для указания того, что нам нужен не инстанс класса, а сам класс, применяется конструкция: typeof Class
addModule(ModuleClass:typeof Module) { this.modules[module.name] = ModuleClass }
getModule(name:string):typeof Module { return this.modules[name] }
addModules(modules:typeof Module[]) {
}
моя ошибка заключалась в том что я использовал устаревший синтаксис типа typeof(Module) который я нагуглил в обсуждении разработчиков тайпскрипта которое они вели аж в 2012 году ^_^

Убрать последнюю запятую в масиве

$items = []; foreach($product_filters as $product_filter) { $items[$product_filter["id"]][] = $product_filter; } foreach($items as $group) { echo " {$group[0]["name"]} ";
foreach($group as $filter) { echo "{$filter['group']}, "; } echo ""; }
Получается что ко всем элементам добавляется в конце запятая, нужно что бы к последнему элементу она не добавлялась
Результат кода
Заголовок 1 Текст 1, Текст 2, Заголовок 2 Текст 3, Текст 4, Заголовок 3 Текст 5,
А должно
Заголовок 1 Текст 1, Текст 2 Заголовок 2 Текст 3, Текст 4 Заголовок 3 Текст 5


Ответ

$numItems = count($group); $i = 0; foreach($group as $filter) {
if(++$i === $numItems) echo "{$filter['group']} "; else echo "{$filter['group']}, ";
}

Cвойство класса типа текст и метод для возврата этого свойства

Если нужно использовать текстовое поле в классе в private, и написать public метод для получения значения этого поля, как лучше сделать? Сейчас я для хранения пытаюсь использоватьchar* pole либо char pole[10]; Если я правильно понимаю, вернуть массив char нельзя, а как тогда быть?
#include class MyClass { public: int getPole1() { return pole1; } void setPole1(int n) { pole1 = n; } //здесь должны быть аналогичные методы для поля pole2 private: int pole1; char pole2[10]; };
int main() { MyClass my; //здесь я должен установить значение pole2 и затем его получить return 0; }


Ответ

Если у вас учебное задание, то для передачи строки надо использовать тип const char * (он же char const *). Массив символов может неявно приводиться к этому типу данных.
Но хранить в классе строку в виде указателя - нельзя, ведь время жизни экземпляра класса и время жизни строки может и не совпадать. Поэтому в классе надо хранить массив символов, и при записи значения свойства надо копировать строку из параметра в массив либо в цикле, либо при помощи strncpy
Если же у вас реальная задача - то подключайте и просто используйте std::string

Карта гексагональной доски

Имеем гексагональную доску (см.рисунок) с длиной грани D Имеем три измерения (направления): красное, синее и зеленое Имеем номера линий по трем направлениям (конкретные значения не критичны, они могут быть любыми)
Необходимо составить карту зависимостей номера линии в измерении, позиции ячейки в этой линии для каждой ячейки всей доски. То есть для номера 1 нужно получить данные по трем измерениям: 1:(1,0), 2:(7,0), 3:(1,0) аналогично к примеру для номера 21: 1:(3,5), 2:(6,3), 3:(10,3) (3,5) например означает линия 3, ячейка 5.
Для красного измерения все весьма просто:
S = K * D + N + summ(range(1,K-1)) - 2*summ(range(1,K-D))
где
K - номер линии D - размер доски (меньшая грань) N - номер ячейки в линии range - функция, возвращающая диапазон, а если левая граница больше правой, то возвращающая 0 S - номер ячейки для всей доски
Никак не могу сообразить, как вычислить два других измерения?


Ответ

Воспользовался советом @KromStern:
У вас странная координатная сетка. Обычно гексы представляют как 2-мерный массив со смещением каждой нечетной линии на 0,5 в отрисовке и доступом к 6 соседям вместо 8 в логике.
Все получилось значительно проще и нагляднее:
---*-*-*--- --*-*-*-*-- -*-*-*-*-*- --*-*-*-*-- ---*-*-*---
Алгоритм прост:
создаем промежуточный прямоугольный массив по схеме выше вычисляем формулы для трех измерений: dim1, dim2, dim3 заполняем промежуточный массив перенумеровываем ключи промежуточного массива, начиная с нуля
Для Python получился следующий код, создающий карту доски:
def dim1( k, n, d ): y = k x = abs( k - d + 1) + 2 * n return [ y, x ]
def dim2( k, n, d ): t = k-d+1 y = n if t>0: y+= t x = abs( 1-d )+2*k-n if t>0: x-= t return [ y, x ]
def dim3( k, n, d ): t1 = k - d + 1 t2 = d - k - 1 y = n if t2>0: y+=t2 x = k + n if t1>0: x+=t1 return [ y, x ]
def pushToRes( y, x, d, val, res, dimens ): ind = y*4*d+x if ( not ind in res.keys() ): res[ind] = {} res[ind][ dimens ] = val
res = {} d= 7 lens = list(range(d,2*d))+list(range(2*d-2,d-1,-1)) # d=3, lens = [3,4,5,4,3]
for i in range( 0, 2*d-1 ): for j in range( lens[i] ): d1 = dim1( i, j ,d ) d2 = dim2( i, j ,d ) d3 = dim3( i, j ,d ) pushToRes( d1[0], d1[1], d, [i,j], res, 1 ) pushToRes( d2[0], d2[1], d, [i,j], res, 2 ) pushToRes( d3[0], d3[1], d, [i,j], res, 3 )
print( res ) print( len( res ) ) // контроль, что число ячеек соответствует действительности x = list(res.keys()) x.sort() res2 = [ res[i] for i in x ] print( res2 )

Можно ли удалить установленные SQL Server`ы, Visual C++, Net Framework?

В "Программы и компоненты" имеется несколько установленных версий Microsoft SQL Server (2005, 2008 Compact Edition, 2012 Express Local и т.п.). Можно ли удалить их и оставить к примеру только Microsoft SQL Server 2014?
Дополнение: Есть еще куча Microsoft Visual C++ 2005..2014 Redistributable (x86) - 10 - 14.0.23506 Можно их снести, а оставить только последнюю версию?
Тот же вопрос по отношению к .NET Framework


Ответ

Не стоит удалять ни .NET Framework, ни MSVC Redistributable.
Дело в том, что они не заменяют друг друга. Если программа требует Redistributable MS VC 2008, то она перестанет работать, когда вы его снесёте, даже если на машине будет старший Redistributable. Таким образом предотвращается DLL Hell: ситуация, когда программа не проверяет версию рантайма, с которой работает, и вылетает из-за бинарной несовместимости версий.

То же касается и фреймворка .NET, хотя здесь немного сложнее: некоторые версии можно сносить, некоторые нет, между ними существуют нетривиальные зависимости
MSDN: Выбор более старых версий
Версии .NET Framework 2.0, 3.0 и 3.5 построены на базе одной и той же версии среды CLR (CLR 2.0). Эти версии представляют последовательные уровни единой установки. Каждая версия построена на базе предыдущих версий. Невозможно запустить версии 2.0, 3.0 и 3.5 параллельно на одном компьютере. При установке версии 3.5 автоматически создаются уровни версий 2.0 и 3.0, и приложения, созданные для версий 2.0, 3.0 и 3.5, могут выполняться в версии 3.5. Однако в .NET Framework 4 этот принцип "слоев" закончился. Начиная с .NET Framework 4, разработчики могут использовать внутрипроцессное параллельное размещение для запуска нескольких версий среды CLR в одном процессе. Кроме того, если в приложении выбрана целевая платформа версии 2.0, 3.0 или 3.5, пользователям может потребоваться включить .NET Framework 3.5 на компьютере с Windows 8 или Windows 8.1, прежде чем они смогут запустить это приложение.
Из версий 4.x, старшие версии являются заменой младшим, так что по идее достаточно сохранить самую старшую из установленных версий (4.6.1 на текущий момент). Версия 3 и 3.5 являются по сути сервис-паками к версии 2, так что если они у вас есть, нужно оставлять и их, и версию 2.
Есть противоречивые сведения о том, стоит ли сносить младшие версии (1.1, 2, 3, 3.5), если у вас уже есть 4+. В теории они должны быть совместимы. Но я бы не рисковал, много места они не занимают.

Дополнение (по результатам обсуждения в чате и комментариях):
Начиная с Windows Server 2003, .NET 2.0 является частью системы, так что он не будет отображаться в списке установленных программ. То же относится к .NET 3.0, начиная с Vista/2008. Это значит, что вам из всего набора фреймворков 2.0, 3.0, 3.5 вам нужно иметь 3.5 (желательно SP1), при этом 2.0 SP2 и 3.0 SP2 у вас будут автоматически (и вы, судя по всему, не сможете их удалить).
С 4.х всё проще: вам нужен лишь последний фреймворк (на данный момент 4.6.1), инсталляция нового должна замещать предыдущий.
Для старинных версий 1.1 и 1.0: программа будет работать и при наличии 2.0, если только она не отконфигурирована на использование конкретной версии, и игнорирование старших версий. То есть, в большинстве случаем удалять их можно, с минимальным риском. Но если рисковать не хочется, можно и оставить.
Дополнение В Windows 10 уже изначально стоит Net framework 2.0, 3.0, 3.5, 4.0
Статья, как проверить установленные версии: Практическое руководство.Определение установленных версий платформы .NET Framework

Теоретически, можно удалять версии, если вы точно знаете, что они не нужны ни одной из программ на вашей машине. Но это по сути задание не для человека, а для системы управления зависимостями. Лучше неё с задачей никто не справится.

Не отображается иконка приложения - C# WinForms


Добавил иконку в свойствах проекта, после компиляции у приложения отображается стандартная иконка. Эта же иконка прекрасно работает в WPF приложении.
В чём может быть проблема?


Ответ

Дизайнер view -> кликни на форму -> Properties -> Icon -> клик на [...] -> выбери иконку формата .ico -> OK
UPDATE:
Если поставить таким образом, то и значок формы и тот значок который отображается в панели задач - будет одинаковым. А если поставить через Свойства проекта -> Значок и манифест, то после компиляции поменяется иконка .exe файла. ("Путь проекта"/bin/Debug (или Release))

Где используется ниббл?

Для чего нужен ниббл, если есть байт? Хочу посмотреть примеры использования ниббл


Ответ

Копипаста, настало твое время
В компьютерной графике иногда используется 4-битная глубина цвета, то есть палитра из 16 цветов. Особенно употребителен был 4-битный цвет для адаптеров EGA. LPT-порт, даже на самом старом PC, может передавать данные от принтера к компьютеру по одному нибблу, используя специальные линии состояния. Эта возможность используется некоторыми периферийными устройствами, подключаемыми через такой порт. Кодовая страница CP866 Октет состоит из двух нибблов. Шестнадцатеричное представление октетов (то есть разложение множества 256 значений октетов в прямое произведение 16×16) используется для наглядного представления этого множества, в частности для изображения кодовых страниц в виде таблиц. На рисунке — множество октетов (символы альтернативной кодировки) в виде таблицы. Слева отложен старший ниббл (возрастает снизу вверх), снизу отложен младший ниббл (возрастает слева направо). При использовании двоично-десятичного кода одна десятичная цифра хранится в одном ниббле. Аналогично метру, килограмму, литру, секунде и другим единицам измерения, в которых используются названия: полметра, полкилограмма, поллитра, полсекунды, а не их специальные названия, на практике применяется название — полубайт, а название ниббл не прижилось.
Источник: Ниббл - Википедия
От себя:
Лично я на практике сталкивался только с двоично-десятичным кодом во времена изучения ассемблера. В некоторых случаях он в разы удобее стандартного бинарного представления числа - например, преобразования числа в строку и обратно в нем проводятся гораздо проще. Не говоря уже про отладку.

Как называется виджет с вкладками?


Подскажите как сделать 2 такие кнопки.
Это TabLayout или что? Меня больше всего смущает белая полоска над активной кнопкой


Ответ

На картинке у Вас изображен TabLayout - Здесь находится хороший пример полностью реализованный и интуитивно понятный с объяснениями и комментариями и самое главное сделан в стиле material design как у Вас в примере.
P.S. Там очень много нужного и смысла нет в показе одного кусочка кода, поэтому прошу не удалять данный ответ:)

date() почему выводит не локальное время?

Нашёл скрипт вывода даты на русском языке , но она выводит время не с моего компа , где ошибка ?
function rusdate($d, $format = 'j %MONTH% Y', $offset = 0) { $montharr = array( 'января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'); $dayarr = array( 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота', 'воскресенье');
$d += 3600 * $offset;
$sarr = array('/%MONTH%/i', '/%DAYWEEK%/i'); $rarr = array( $montharr[date("m", $d) - 1], $dayarr[date("N", $d) - 1] );
$format = preg_replace($sarr, $rarr, $format); return date($format, $d); }
Вызов скрипта

а выводит время на час больше :
воскресенье, 15 мая 2016, 10:38
а у меня :
воскресенье, 15 мая 2016, 9:38


Ответ

Если не сложно посмотрите в php.ini или через функцию phpinfo() ваш часовой пояс, установленный в директиве date.timezone
date.timezone = 'Europe/Moscow'
Он соответствует часовому поясу, где вы находитесь? У меня ваш скрипт отработал без ошибок.

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

Как заменить текст с помощью выражений ?
Вместо [img]ссылка[/img], заменить на
Вот текст:
Сегодня была очень хорошая погода, небо было безоблачное [img]http://iconizer.net/files/Iconsland_Weather/thumb/128/Sunny.png[/img], был слышен легкий шелест листьев на ветру [img]http://ictютуе/files/thumb/128/Sunny2.png[/img]. Безоблачное небо мне напоминало голубой топаз.
Интересуют варианты на Jquery, JS и php тоже не помешалобы.


Ответ

Приблизительно так:
s = "Сегодня была очень хорошая погода, небо было безоблачное [img]http://iconizer.net/files/Iconsland_Weather/thumb/128/Sunny.png[/img], был слышен легкий шелест листьев на ветру [img]http://ictютуе/files/thumb/128/Sunny2.png[/img]. Безоблачное небо мне напоминало голубой топаз."; var d = document.createElement('div'); d.textContent = s; s = d.innerHTML.replace(/\[img\](.*?)\[\/img\]/g, '')
Надо:
нормально реализовать экранирование (не через создание div) подумать о некорректных bb-кодах подумать об экранировании в ссылках

SQL Выборка по уникальному полю и группировка

Подскажите по выборке повторяющихся значений. Есть таблица
( 1, 'user1', 'Новое сообщение', '2014-02-15' ), ( 2, 'user2', 'Новое сообщение', '2015-05-07' ), ( 3, 'user3', 'Новое сообщение', '2015-09-12' ), ( 4, 'user2', 'Регистрация', '2016-05-16' ), ( 5, 'user1', 'Новое сообщение', '2016-05-16' ), ( 6, 'user4', 'Создание темы', '2016-05-12' )
Как написать запрос, что бы получить сколько юзеров в каждом году написали сообщения впервые,т.е. должно на выходе быть
2014 1 2015 2 2016 0
Если написать данный код
SELECT Extract(YEAR from Date) As Year, Count(DISTINCT user) AS Count FROM table WHERE Type LIKE 'Новое%' GROUP BY Extract(YEAR from Date)
то на выходе будет
Year Count 2014 1 2015 2 2016 1
И я, собственно, понимаю почему так происходит. Как решить данную задачу ?


Ответ

Например так:
Сначала отобрать минимальный номер года, в котором у пользователя появилось новое сообщение, а потом из всего этого сделать группировку с суммированием по годам:
select Year, count(user) as Count from ( select min(extract(YEAR from Date)) as Year, user as User from table where Type like 'Новое%' group by user ) as FirstMessageYears group by Year
Уникальность обеспечивается тем, что мы можем получить только одну минимальную дату для каждого пользователя, так что distinct не понадобится.
Для дополнения строками с годами, по которым есть сообщения, но не первые, можно воспользоваться тем, что count(null) возвращает 0:
Внутренний запрос усложнился тем, что теперь он возвращает года, для которых нет пользователя с первым сообщением, со значение null в колонке пользователя.
select AllYears.Year, count(FirstMessageYears.User) as Count from ( select min(extract(YEAR from Date)) as Year, user as User from table where Type like 'Новое%' group by user ) as FirstMessageYears right join ( select distinct extract(YEAR from Date) as Year from table ) as AllYears on FirstMessageYears.Year = AllYears.Year group by AllYears.Year

Давайте попробуем разобраться. Начинаем "выполнять" SQL запрос "изнутри", т.е. с тех частей, что находятся на максимальном уровне вложенности. В нашем случае, вложенным является сложный подзапрос:
( select min(extract(YEAR from Date)) as Year, user as User from table where Type like 'Новое%' group by user ) as FirstMessageYears right join ( select distinct extract(YEAR from Date) as Year from table ) as AllYears on FirstMessageYears.Year = AllYears.Year

Чтобы понять, что этот подзапрос возвращает, давайте разбирать его на запчасти:
( select min(extract(YEAR from Date)) as Year, user as User from table where Type like 'Новое%' group by user ) as FirstMessageYears
right join
( select distinct extract(YEAR from Date) as Year from table ) as AllYears

Вот, уже немножно легче. Имеем два запроса, каждый возвращает таблицу, потом эти таблицы объединяются посредством операции с непонятным названием right join
Сначала разберёмся, что возвращают каждая из частей перед объединением.
Первый результат подзапроса с красноречивым названием FirstMessageYears будет содержать две колонки: пользователь + дата первого сообщения.
Второй результат подзапроса с названием AllYears будет содержать одну колонку, в которой будут перечислены все года, встречающиеся в исходной таблице table
Что будет, если применить к этим двум наборам операцию right join? Получится таблица, состоящая из двух столбцов, номер года и пользователь. Логически, этот набор заполняется в 2 этапа:
Сначала, в результат объединения попадают те строчки из набора AllYears, для которых нет соответствия в наборе FirstMessageYears. Поле пользователь для этих строчек остаётся null
Потом, в результат объединения попадают те строчки из набора FirstMessageYears, для которых есть соответствие в наборе AllYears. Поле пользователь для этих строчек берётся из набора FirstMessageYears

Остаётся провести по этому результирующему колдовству группировку:
select AllYears.Year, count(FirstMessageYears.User) as Count from [результат выполнения подзапроса] group by Year
а мы помним, что колонка FirstMessageYears.User оказалась со значеним null в тех строчках, которые соответствуют годам, в которые не было первого сообщения от кого-либо из пользователей. Count(null) возвращает 0. Ву-а-ля.

не могу повторно использовать переменную

есть функция:
function buildUser(first, last) { let fullName = first + " " + last; return {first, last, fullName}; }
я создаю переменные с помощью неё:
let {first, last, fullName} = buildUser("User1", "LastName");
console.log(first); console.log(last); console.log(fullName);
всё работает, но почему я не могу создать ещё одни переменные никак не пойму. делаю так:
let {first, last, fullName} = buildUser("test1", "test1");
console.log(first); console.log(last); console.log(fullName);
получаю синтаксическую ошибку:
SyntaxError: redeclaration of let first let {first, last, fullName} = buildUser("test1", "test1");
если делаю с новыми переменнымы то они получаются undefined:
let {first2, last2, fullName2} = buildUser("test1", "test1");
console.log(first2); console.log(last2); console.log(fullName2);
что я упускаю , объясните пожалуйста?
совсем запутался: такой код почему то не работает тоже:
function buildUser2 (first, last, postCount) { let fullNameMy = first + " " + last; const ACTIVE_POST_COUNT = 10;
return { firstMy, lastMy, fullNameMy, isActive(){ return postCount >= ACTIVE_POST_COUNT; } } }
let {firstMy, lastMy, fullNameMy} = buildUser2("test2", "test2");
console.log(firstMy); console.log(lastMy); console.log(fullNameMy);
ошибка:
ReferenceError: can't access lexical declaration `firstMy' before initialization


Ответ

Проблема в операторе let
Повторное объявление той же переменной в том же блоке или функции приведет к выбросу исключения SyntaxError. если делаю с новыми переменными то они получаются undefined:
let {first2, last2, fullName2} = buildUser("test1", "test1");
console.log(first2); console.log(last2); console.log(fullName2);
При реструктуризирующем присваивании важно имя полей.
В функции buildUser возвращается объект
return {first, last, fullName};
это сокращенная форма объявления свойств объекта эквивалентная
{ "first": first, "last": last, "fullName": fullName, }
В присваивании ожидается: first2, last2, fullName2 в возвращаемом объекте их нет. поэтому они принимают значение по умолчанию: undefined
Проблем с именами свойств объектов можно избежать если возвращать из функции не объект а массив
function buildUser(first, last) { let fullName = first + " " + last; return [first, last, fullName]; } let [first, last, fullName] = buildUser("User1", "LastName"); console.log(first,last,fullName); let [first2, last2, fullName2] = buildUser("test1", "test1"); console.log(first2, last2, fullName2);
Обновление:
ошибка:
ReferenceError: can't access lexical declaration `firstMy' before initialization
В стандарте ECMAScript 2015 переменные, объявленный оператором let, переносятся наверх блока. Но если вы сошлетесь в блоке на переменную, до того как она будет объявлена оператором let, то это приведет к выбросу исключения ReferenceError, потому что переменная находится во "временной мертвой зоне" с начала блока и до момента ее объявления.

bad interpreter: No such file or directory

Суть проблемы: если ша-бэнг содержит только только имя файла интерпретатора, то bash его не находит и ругается
bad interpreter: No such file or directory
Вот Linux на NAS:
$ bash --version GNU bash, version 4.1.11(2)-release (arm-ffp-linux-uclibcgnueabi) Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later
$ cat howdy.pl #!perl
print "Howdy!
";
$ perl howdy.pl Howdy!
$ ./howdy.pl bash: ./howdy.pl: perl: bad interpreter: No such file or directory
$ hash hits command 1 /ffp/bin/bash 2 /ffp/bin/perl 1 /ffp/bin/cat
$ type perl perl is hashed (/ffp/bin/perl)
$ which perl /ffp/bin/perl
А вот Cygwin 2.5.1 (в 1.7.33 не наблюдал):
$ bash --version GNU bash, version 4.3.42(4)-release (i686-pc-cygwin) Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later
$ ls -l howdy.pl -rwxr-xr-x+ 1 user group 26 May 20 12:28 howdy.pl
$ cat howdy.pl #!perl
print "Howdy!
";
$ perl howdy.pl Howdy!
$ ./howdy.pl -bash: ./howdy.pl: perl: bad interpreter: No such file or directory
$ hash hits command 2 /usr/bin/bash 2 /usr/bin/perl 1 /usr/bin/chmod 1 /usr/bin/cat 2 /usr/bin/ls
$ type perl perl is hashed (/usr/bin/perl)
$ which perl /usr/bin/perl
Права на исполнение есть, никаких CR (^M) нет. В Cygwin 2.5.1 проявляется примерно в 50% случаев, т.е. может запуститься, а может и нет.
Проблема, конечно, не великая, но ИМХО так быть не должно.


Ответ

В вашем случае ошибка возникает из-за того, что строка-shebang #!perl эквивалентна #!./perl. Ваш скрипт пытается выполниться интерпретатором, находящимся в текущей директории, и, соответственно, говорит bad interpreter: No such file or directory, потому что в текущей директории у вас нет файла perl.
В виде эксперимента: если вы разместите perl-интерпретатор рядом со скриптом (что довольно странно), то этой ошибки не будет.
...#!interpreter is equivalent to #!./interpreter, however, it's not of any practical use...
The #! magic, details about the shebang/hash-bang mechanism on various Unix flavours

SQL Выборка строк с нарушением

Подскажите в каком направлении думать. Есть таблица, такого типа:
create table table1( Id int primary key, User nvarchar(30), Typeofposition nvarchar(60), PayDate date, Price numeric(15,2) );
insert into table( Id, User, Typeofposition, PayDate, Price ) ( 1, 'user1', 'Взнос', '20120216', 1000 ), ( 2, 'user1', 'использование', '20120216', 0 ), ( 3, 'user1', 'использование', '20120215', 1000 ), ( 4, 'user2', 'использование', '20120220', 0 ), ( 5, 'user2', 'использование', '20120223', 300 ), ( 6, 'user2', 'Взнос', '20120321', 1000 ), ( 7, 'user3', 'использование', '20120521', 0 ), ( 8, 'user1', 'использование', '20151015', 0 )
По правилам, сервисом можно пользоваться двумя способами.
1) Либо сразу взносишь 1000 руб и можешь пользоваться сервисом бесплатно в течении 4 месяцев (заказ записывается в БД с ценой 0);
2)При каждом использовании оплачиваешь услугу
написать SQL-запрос, который вернет из таблицы table позиции «активность», оформленные с нарушениями. Так, в приведенной выше таблице нарушены позиции :
Id = 4 - "использование" с ценой 0 проведен раньше "взноса"; Id = 7 - "использование" с ценой 0 проведен без оплаты "взноса"; Id = 8 - "использование" с ценой 0 проведено спустя более 4 месяцев после оплаты "взноса".


Ответ

Вариант 1. Курсор
Можно отсортировать данные по пользователю и дате. Завести табличную переменную, где будем хранить нарушения, аналогичную по структуре исходной таблице.
Открыть по запросу курсор и по каждому пользователю при каждом взносе запоминать PayDate в переменную @last_pay_date, а для использований с нулевой стоимостью считать datediff от последней запомненной даты.
Для использований: если datediff превышает 4 месяца или @last_pay_date is null - добавлять строку в табличную переменную.
При переходе к следующему пользователю - обнулять @last_pay_date
В конце - вернуть содержимое.
declare @violations table( Id int, [User] nvarchar(30), Typeofposition nvarchar(60), PayDate date, Price numeric(15,2))
declare @cur_id int, @cur_user nvarchar(30), @prev_user nvarchar(30), @cur_type nvarchar(60), @cur_date date, @cur_price numeric(15,2), @last_pay_date date
DECLARE cur CURSOR FOR SELECT Id, [User], Typeofposition, PayDate, Price FROM table1 WHERE Typeofposition = N'Взнос' OR Price = 0 ORDER BY [User], PayDate
OPEN cur
FETCH NEXT FROM cur INTO @cur_id, @cur_user, @cur_type, @cur_date, @cur_price
WHILE @@FETCH_STATUS = 0 BEGIN IF @cur_user <> @prev_user OR @prev_user IS NULL BEGIN SET @last_pay_date = null SET @prev_user = @cur_user END
IF @cur_type = N'Взнос' SET @last_pay_date = @cur_date ELSE BEGIN IF @last_pay_date IS NULL OR datediff(month, @last_pay_date, @cur_date) > 4 INSERT INTO @violations VALUES (@cur_id, @cur_user, @cur_type, @cur_date, @cur_price) END
FETCH NEXT FROM cur INTO @cur_id, @cur_user, @cur_type, @cur_date, @cur_price END
CLOSE cur DEALLOCATE cur
SELECT * FROM @violations
Пример на SQLFiddle

Вариант 2. Оконная функция
Оконные функции позволяют вычислить некоторое агрегатное значение для каждой строки, опираясь на некоторые диапазоны строк, относительно текущей, или секции (похожие на группы в GROUP BY).
Рассмотрим поэтапно:
Сортируем по пользователю и дате. Отбрасываем использования с ненулевой оплатой.
SELECT * FROM table1 WHERE Typeofposition = N'Взнос' OR Price = 0 ORDER BY [User], PayDate Разбиваем на секции по пользователю с сортировкой по дате. Для каждой секции вычисляем максимальную скользящую дату внесения платежа (максимальную дату с начала секции и до текущей строки). Для "взносов" - это PayDate, для использований - null.
SELECT * , MAX( CASE Typeofposition WHEN N'Взнос' THEN PayDate ELSE null END ) OVER (PARTITION BY [User] ORDER BY PayDate) as LastPayDate, FROM table1 WHERE Typeofposition = N'Взнос' OR Price = 0 ORDER BY [User], PayDate Вычисляем datediff в месяцах между PayDate и максимальной скользящей датой внесения платежа.
SELECT * , datediff(month, MAX( CASE Typeofposition WHEN N'Взнос' THEN PayDate ELSE null END ) OVER (PARTITION BY [User] ORDER BY PayDate), PayDate) as MonthsSinceLastPayment
FROM table1 WHERE Typeofposition = N'Взнос' OR Price = 0 ORDER BY [User], PayDate OVER-выражения нельзя использовать в WHERE, поэтому обернем все в SELECT и выберем строки, где MonthsSinceLastPayment не задан (взносов еще не было) или превышает 4 месяца:
SELECT * FROM (SELECT * , datediff(month, MAX( CASE Typeofposition WHEN N'Взнос' THEN PayDate ELSE null END ) OVER (PARTITION BY [User] ORDER BY PayDate), PayDate) as MonthsSinceLastPayment
FROM table1 WHERE Typeofposition = N'Взнос' OR Price = 0 ) Violations WHERE MonthsSinceLastPayment >= 4 OR MonthsSinceLastPayment IS NULL
Пример на SQLFiddle