Страницы

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

вторник, 12 марта 2019 г.

Алгоритм поиска в тексте

Всем доброго времени суток. Хотел бы выслушать идеи алгоритмов для следующего задания. Пишу на Java. Имеется .txt фаил допустим:
стул,стол,книга,табуретка диван,мусор,ноутбук,стол ручка,зарядка,мышь,лампа
Я запрашиваю у пользователя слово. Допустим слово - стол. И мне нужно вывести в другой .txt фаил только те столбцы где находится слово стол, т.е в данном примере было бы:
стол мусор зарядка табуретка стол лампа
P.s была идея идти по строке, проверять каждое слово на сходство, и при этом вести счётчик для каждой итерации по словам в строке. Т.е если бы во второй строке попалось бы нужное слово, то индекс добавлял бы в массив. На выходе у меня был бы массив с номерами столбцов в которых есть искомое слово. Но как следовать дальше не знаю. Буду благодарен за любые идеи.


Ответ

Лучше идти не по строкам, а по столбцам. Тогда если в столбце встретилось слово, то можно сразу вывести этот столбец и перейти к следующему.
String wordToFind = ... String[][] words = ...
int numberRows = words.length; int numberColumns = words[0].length;
for (int j = 0; j < numberColumns; ++j) { boolean columnContainsWord = false; for (int i = 0; i < numberRows; ++i) { if (wordToFind.equals(words[i][j])) { columnContainsWord = true; break; } }
if (columnContainsWord) { // выводим столбец for (int i = 0; i < numberRows; ++i) { System.out.println(words[i][j]); } } }

Правильно ли я понял рекурсию?

Неделю боролся с осознанием рекурсии, изучаю учебник Learn.Javascript. Пока в голове такая каша:
Рекурсия это вызов функции внутри себя же, но уже с другим параметром В решении конкретной задачи параметр должен уменьшаться или увеличиваться Параметр будет уменьшаться/увеличиваться до тех пор пока не запнётся на условии Условие на котором запнётся рекурсия должно вернуть простейшее решение уже не требующее очередного вызова функции Все предыдущие функции ждут решения следующей, в том числе простейшего решения. Место где они ждут называется Стек (с англ. Stack == стог, стопка) Когда рекурсия запнётся на простейшем решении, результаты начнут возвращаться в обратном порядке. Из конца в начало, с глубины на поверхность. Функции которые получили решение будут уходить из Стека начиная с последней. Останется только довольная первая, которая всю эту заварушку устроила.
Следует различать три вещи:
Рекурсия это общее явление, оно встречается не только в программировании - в природе, рисовании и т.д.... Чтобы использовать это явление для решения задач, оно должно возвращать нам результат. Нужно объяснить компьютеру с каким шагом двигаться, где остановиться и что возвращать. А вот Стек это уже чисто программное явление, т.к. это ячейки компьютерной памяти. На каждом шаге компьютер будет записывать всё что происходит чтобы не заблудиться именно в Стек.
Можно такой пример привести: В армии генерал отправил майора за спиртом, майор отправил капитана за спиртом, капитан отправил лейтенанта за спиртом, лейтенант отправил сержанта за спиртом, сержант отправил рядового за спиртом. Рядовому некого отправлять, это очевидно - он пошёл и нашёл спирт. Затем спирт пошёл обратно по цепочке рядовой - сержант - лейтенант - капитан - майор - генерал. Генерал доволен, всё чётко.
Друзья, сейчас очень нужна ваша критика - дополните или поправьте чтобы лучше понять рекурсию.


Ответ

Практически все из написанного верно, но:
Рекурсия это вызов функции внутри себя же, но уже с другим параметром
Не с другим параметром, а с другим значением параметра или параметров.
В решении конкретной задачи параметр должен уменьшаться или увеличиваться
Не совсем верно. Параметр или параметры могут быть просто неким признаком, в общем всем тем, что можно проверить в условии, которое сможет разветвиться на два и более решений, при этом одно или несколько из этих решений могут как вести на очередной виток рекурсии, так и на выход из нее.
Условие на котором запнётся рекурсия должно вернуть простейшее решение уже не требующее очередного вызова функции
Решение не то, что бы простейшее, оно просто решение, некий результат некоего сравнения.

Как сделать тень только с одной стороны?

Хочу сделать тень у div блока, но чтобы она была только с одной стороны - сверху.
Исходный стиль:
div { box-shadow: 0 15px 30px 10px rgba(0, 0, 0, .5); width: 200px; height: 150px; overflow: hidden; margin: 30px; }


Проблема заключается в том, что тень присутствует так же и слева и справа (совсем капельку и снизу, что тоже является недопустимым). Различные манипуляции с 2-4 значениями ни к чему не привели (да и позиционирование хочется сохранить текущее). Тень так или иначе все равно присутствует по бокам.
Как все же добиться желаемого результата?


Ответ

В моем случае получилось обыграть ситуацию с помощью внутренней тени:
div { box-shadow: inset 0 -7px 20px -10px rgba(0, 0, 0, .5);/* получившаяся тень */ width: 200px; height: 150px; overflow: hidden; margin: 30px; }


По сути раннее внешнее позиционирование на топ'е блока ушло на внутреннее нижнее позиционирование соседнего блока. В результате все выглядит достаточно чисто.
Также, пока писал этот ответ, в голову пришла альтернативная идея по внутренней реализации в соседнем блоке - это с помощью linear-gradient

Передача данных между фрагментами через модель в Clean Architecture

Подскажите поподробней как реализовать такое? Нужно передать данные, например, какие EditText или CheckBox были выбраны на предыдущем фрагменте, чтобы работать с ними в текущем фрагменте.
Не в чистой архитектуре передавалось через
Bundle bundle = new Bundle(); bundle.putString("some_key", "some string"); fragment.setArguments(bundle);
Далее вытаскиваем
getArguments().getString("some_key")
Но слышал. что в чистой архитектуре это делается таким способом
Создается модель. Эта модель является глобальной для всех презентеров внутри этой активити. Остальные презентеры при надобности имеют право писать в модель, а презентер фрагмента должен соответственно реагировать на ее изменения" я имею ввиду взаимодействие через модель
Хотелось бы в идеале увидеть пример, как это делается. Создавать свой репозиторий, для того чтобы передать пару строк или объект между фрагментами? Я использую Dagger2 можно ли тупо провайдить
Model provideModel(){ return new Model(); }
Сейчас у меня в каждый презентер своя модель попадает. Тогда нужно ее сделать синглтоном? Конкретно в моем случае я кликаю на один из элементов RecyclerView и мне нужно передать значение этого элемента.
В общем пока нет понимания правильности.


Ответ

Локальная модель нужна для передачи результата с экрана на предыдущий либо между двумя фрагментами на экране одновременно.
Для запуска нового экрана, параметры запуска передаются в аргументах через бандл как и всегда. То есть схема такая:
Во вью происходит клик на элемент в списке -> у презентера вызывается метод onItemClick(item) -> Презентер запускает новый экран, передав ему нужные параметры

КриптоПро.NET SDK работа с ЭЦП

Как подписать и зашифровать файл используя библиотеку КриптоПро.NET SDK имея USB токен? Алг. подписи ГОСТ 34.10-2001(512 bits) Алг. хэша ГОСТ 34-11-94
Я имею файл в формате p7s.p7m. Его содержимое разделено тегами
----- BEGIN PKCS7 ENCRYPTED ----- --- END PKCS7 ENCRYPTED -----


Ответ

Я решил идти по пути наименьшего сопротивления и использовать консольную утилиту Cyptcp компании КриптоПро. Для работы утилиты нужен криптопровайдер КриптоПро CSP. КриптоПро CSP на одну машине стоит около 2 000 руб, а Cyptcp около 700 руб. Cyptcp и АРМ КриптоПро совместимы между собой.
Формирую команды:
///

/// Формирование команд для утилиты Cyptcp /// public static class Command { /// /// Команда на запуск дешифрования /// /// Имя сертификата /// Путь к защифрованному файлу /// Путь к дешифрованному файлу /// public static string Decript(string nameCertificate, string pathEncryptedFile, string pathSave) { return "-decr -dn \"" + nameCertificate + "\" " +"\""+ pathEncryptedFile + "\" \"" + pathSave+"\""; }
/// /// Проверка подписи. Сертификат выбирается из хранилища сертификатов /// /// Путь к подписанному файлу /// Путь к очищенному от подписи файлу /// public static string VerificationSignature(string pathSignFile, string pathFile) { return "-verify -verall " + "\"" + pathSignFile + "\" \"" + pathFile + "\""; }
public static string Sign(string nameCertificate, string pathFile, string pathSignedFile) { return "-sign -dn \"" + nameCertificate + "\" " + "\"" + pathFile + "\" \"" + pathSignedFile + "\""; }
public static string Encrypt(string nameRecipientCertificate, string pathSigFile, string pathSave) { return "-encr -dn \"" + nameRecipientCertificate + "\" " + "\"" + pathSigFile + "\" \"" + pathSave + "\""; } }
Запуск утилиты на выполнение команды:
private void RunCommand(string command, string pathApplication) { using (Process process = new Process()) { //Имя файла. process.StartInfo.FileName = pathApplication; //Директория. process.StartInfo.WorkingDirectory = Path.GetDirectoryName(pathApplication); //Команда. process.StartInfo.Arguments = command;
//Не показывать окно приложения. process.StartInfo.CreateNoWindow = true; process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.StandardOutputEncoding = Encoding.Default;
process.Start();
//Ответ на диалог выбора сертификата process.StandardInput.WriteLine("y"); } }

Сериализация свойства коллекции

Есть такой класс:
public class ChapterCollection : ObservableCollection { public bool? IsSelectedAll { get { return _isSelectedAll; } set { _isSelectedAll = value; OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsSelectedAll))); } } }
При его сериализации в XML свойство IsSelectedAll не сериализуется. Только коллекция объектов ChapterVM
Как сериализовать свойство?
Сериализация происходит так:
public static void SerializeToXml(string path, object saveObject) { var formatter = new XmlSerializer(saveObject.GetType()); using (FileStream fs = new FileStream(path, FileMode.Create)) { formatter.Serialize(fs, saveObject); } }


Ответ

Наиболее простым решением является отказ от наследования в пользу композиции. Действительно, логично предположить что ChapterCollection не просто "является" коллекцией ChapterVM, а содержит в себе коллекцию ChapterVM и также некоторые другие свойства, как признак выделенности элементов коллекции и т.п. Зы. Недаром умные книги по проектированию пишут
Предпочитайте композицию наследованию

Если всё же вы намерены оставить наследование, для переопределения действий сериализатора необходимо реализовать интерфейс IXmlSerializable. Сделать это можно примерно так:
public class ChapterCollection : ObservableCollection, IXmlSerializable { bool? _isSelectedAll; public bool? IsSelectedAll { get { return _isSelectedAll; } set { _isSelectedAll = value; OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsSelectedAll))); } }
public XmlSchema GetSchema() => null;
public void ReadXml(XmlReader reader) { reader.ReadStartElement();
// Читаем из потока дополнительные свойства вручную IsSelectedAll = reader.ReadElementContentAsBoolean(nameof(IsSelectedAll), ""); // Читаем элементы коллекции XmlSerializer ser = new XmlSerializer(typeof(Chapter)); while (reader.NodeType == XmlNodeType.Element) Add((Chapter)ser.Deserialize(reader));
reader.ReadEndElement(); }
public void WriteXml(XmlWriter writer) { // Сериализуем дополнительные свойства вручную writer.WriteStartElement(nameof(IsSelectedAll)); writer.WriteValue(IsSelectedAll); writer.WriteEndElement(); // Сериализуем элементы коллекции XmlSerializer ser = new XmlSerializer(typeof(Chapter)); foreach (var ch in this) ser.Serialize(writer, ch); } }

Дополню ответ вариантом сериализации при композиции.
Наш класс коллекции превращается в такой:
public class ChapterCollection { public bool? IsSelectedAll { get; set; }
public ObservableCollection Collection { get; } = new ObservableCollection(); }
Обратите внимание, создать экземпляр нужно обязательно вручную, сериализатор не может создавать "кастомные" коллекции, поэтому он не заполнит ее: = new ObservableCollection(); Но зато открывать свойство коллекции на запись (set;) не нужно.
Теперь вы можете использовать Linq, но придется указать имя этого свойства-коллекции:
myChapterCollection.Collection.Select(...);
Если вы реализуете IEnumerable<>, то сериализатор опять начнет думать что это коллекция и потеряет свойства, да еще к тому же потребует реализовать нетипизированный метод Add(object), что уже некрасиво и добавляет некоторую хрупкость.
PS: благодаря утиной типизации C# можно все же добавить маленький кусочек сахара, добавив в класс метод:
public IEnumerator GetEnumerator() => ((IEnumerable)Collection).GetEnumerator();
это хоть и не даст воспользоваться LINQ на экземпляре класса, но позволит упростить код foreach
// myChapterCollection.Collection писать не требуется: foreach (var chapter in myChapterCollection) ...

Ошибка при подключение к MySql: “QSqlDatabase: QMYSQL driver not loaded”

При таком коде:
db = QtSql.QSqlDatabase.addDatabase('QMYSQL') db.setHostName('localhost') db.setUserName('root') db.setPassword('1234') db.setDatabaseName('test') db.open() print(db.lastError().text())
В консоль выводится следующие:
python gui.py QSqlDatabase: QMYSQL driver not loaded QSqlDatabase: available drivers: QSQLITE QMYSQL QMYSQL3 QODBC QODBC3 QPSQL QPSQL7 Driver not loaded Driver not loaded
Библиотеки qsqlite.dll, qsqlmysql.dll, qsqlodbc.dll, qsqlpsql.dll существуют и находятся в папке
C:\Python\Lib\site-packages\PyQt5\Qt\plugins\sqldrivers
Использую Windows 10 x64, Python 3.6.1, PyQt 5.8, MySql 5.7.
Такой вопрос уже был задан здесь, но решение, которое в нем содержится, мою проблему не решило.
Что надо сделать, чтобы установить соединение с базой?


Ответ

Для подключения нужно добавлять в среду переменных в переменную PATH полный путь к /MySQL/lib.
В моем случае полный путь выглядит так:
C:\Program Files (x86)\MySQL\MySQL Server 5.7\lib
Затем перезагрузить или выйти из системы, чтобы это добавление вступило в силу, вот что я и сделал, и в чем состояло решение проблемы.

Как сделать широкий текстовый курсор в input type=text

Нужно зделать широкий текстовый курсор в input type=text и чтобы при перемещении его назад он становился под буквой, а та окрашивалась в контрастный цвет. Интернет весь перерыл, сам наделал кучу полурабочих костылей. Теперь пишу сюда, может кто-то с подобной проблемой сталкивался и терпения у него было по более... Можно и с jQuery, мне уже фиолетово да и времени нет...


Ответ

Написал решение сам, может кому пригодится:
var txt = document.getElementById('text'); var wrp = document.getElementById('wrapper'); wrp.onclick = function() { txt.focus(); } setInterval(function() { var pos = getCursorPosition(txt); var val = txt.value; var symb; if (typeof val[pos] == "undefined" || val[pos] == " ") symb = " "; else symb = val[pos]; var curs = "" + symb + ""; var p1 = val.slice(0, pos); var p2 = val.slice(pos + 1, val.lenght); wrp.innerHTML = p1.replace(/ /g, " ") + curs + p2.replace(/ /g, " "); wrp.style.top = (txt.getBoundingClientRect().top + txt.offsetTop + 3) + "px"; wrp.style.left = (txt.getBoundingClientRect().left + txt.offsetLeft + 2) + "px"; txt.style.width = parseInt(document.defaultView.getComputedStyle(wrp).width, 10) + 10 + "px"; }, 10); function getCursorPosition(ctrl) { var caretPos = 0; if (document.selection) { ctrl.focus(); var sel = document.selection.createRange(); sel.moveStart('character', -ctrl.value.length); caretPos = sel.text.length; } else if (ctrl.selectionStart || ctrl.selectionStart == '0') { caretPos = ctrl.selectionStart; } return caretPos; } #text { font-family: monospace; color: transparent; } #wrapper { font-family: monospace; position: absolute; min-width: 150px; }

Как отслеживать события мыши в Python?

Каким образом отслеживать события мыши в python? Вообще говоря интересует библиотека pynput c его mouse.Listner, но это не принципиально. Причём, интересует не только ЛКМ, ПКМ и колёсико, но и дополнительные клавиши, присутствующие на мышке.
P.S. keyboard.Listner слушает именно клавиатуру. Он не работает с мышью, проверено.


Ответ

В документациии есть пример
from pynput import mouse
def on_move(x, y): print('Pointer moved to {0}'.format( (x, y)))
def on_click(x, y, button, pressed): print('{0} at {1}'.format( 'Pressed' if pressed else 'Released', (x, y))) if not pressed: # Stop listener return False
def on_scroll(x, y, dx, dy): print('Scrolled {0} at {1}'.format( 'down' if dy < 0 else 'up', (x, y)))
# Collect events until released with mouse.Listener( on_move=on_move, on_click=on_click, on_scroll=on_scroll) as listener: listener.join()

Запись/чтение файла Guitar Pro (*.gtp) с помощью c#

Может какую-нибудь либу посоветуете.. или просто принцип работы с такими файлами


Ответ

Это вольный перевод и компиляция из ответов с en-so по ссылке, предложенной в комментариях @maxwell.
Есть приложение на Java c открытым исходным кодом -- TuxGuitar, можете посмотреть его исходники.
Также есть описание формата GTP, полученное реверс-инжинирингом. Также можно посмотреть исходники самого DGuitar, который представляет из себя проигрыватель gtp (.GP4,.GP3,GTP). Правда, для этого нужно понимать Java, так как этот проигрыватель написан на нём.
Также можно посмотреть исходники kguitar, это также проигрыватель gtp но на c++ и qt.
На c# есть приложение просмотрщик gtp для Windows Phone (переехало на git)

Чтение нужного значения с массива куков

Имеются куки:
_ym_uid=1501572828150021607; _ym_isad=2; value=11; _ga=GA1.2.889728148.1501572828; _gid=GA1.2.353711974.1501572828; _gat=1; _ym_visorc_45462804=w
Как мне получить значение 11 из value=11; (куки могут меняться местами, 11 тоже может менять от 0 до 99)?
Мой код был:

Он перестал работать после подключения счетчиков метрики, так как куков стало больше и, получается, что я не верно беру нужный кук.


Ответ

На счёт правильности решения не уверен, но можно значение вытащить так:
var s = '_ym_uid=1501572828150021607; _ym_isad=2; value=11; _ga=GA1.2.889728148.1501572828; _gid=GA1.2.353711974.1501572828; _gat=1; _ym_visorc_45462804=w'; var value = s.split('value=')[1].split(';')[0];

Помогите с кроссбраузерностью иконок

Так отображается в хроме,
@font-face { font-family: 'Material Icons'; font-style: normal; font-weight: 400; src: url(https://fonts.gstatic.com/s/materialicons/v28/2fcrYFNaTjcS6g4U3t-Y5ewrjPiaoEww8AihgqWRJAo.woff) format('woff'); } .material-icons { font-family: 'Material Icons'; font-weight: normal; font-style: normal; line-height: 1.9; letter-spacing: normal; text-transform: none; white-space: nowrap; word-wrap: normal; direction: ltr; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; } .jub-icon-mask.icon-huge { width: 128px; height: 128px; line-height: 128px; padding: 0; text-align: center; font-size: 64px; box-sizing: content-box; border-radius: 50%!important; } .jub-icon-mask.bg-blue { background-color: #2196F3; color: rgba(255, 255, 255, .87); } i { font-size: 64px; font-weight: 300; }

cloud_done

А так в safari,как исправить?


Ответ

В новых сафари отображается нормально, для старых браузеров используйте код, как указано в мануале
Вместо:
cloud_done
Вставьте:

Ваш пример:
@font-face { font-family: 'Material Icons'; font-style: normal; font-weight: 400; src: url(https://fonts.gstatic.com/s/materialicons/v28/2fcrYFNaTjcS6g4U3t-Y5ewrjPiaoEww8AihgqWRJAo.woff) format('woff'); } .material-icons { font-family: 'Material Icons'; font-weight: normal; font-style: normal; line-height: 1.9; letter-spacing: normal; text-transform: none; white-space: nowrap; word-wrap: normal; direction: ltr; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; } .jub-icon-mask.icon-huge { width: 128px; height: 128px; line-height: 128px; padding: 0; text-align: center; font-size: 64px; box-sizing: content-box; border-radius: 50%!important; } .jub-icon-mask.bg-blue { background-color: #2196F3; color: rgba(255, 255, 255, .87); } i { font-size: 64px; font-weight: 300; }


Создание приложения для голосового звонка

Техническое задание
Необходимо создать сайт с одной единственной кнопкой "Позвонить". После нажатия, пользователь на угад связывается с таким же пользователем, который нажал на эту кнопку и в ожидании. Затем они могут разговаривать, используя микрофон. Этот сервис для начала должен выдерживать разговор одновременно 10 000 пользователей и сразу необходимо заложить возможность в недалеком будущем создание мобильного приложения. Я так понимаю лучше сразу строить эту систему на микросервисах REST.
Я пока новичок в этой сфере и не знаю, как правильно это называется Интернет-телефония, IP-телефония или VoIP. Пока даже не понял, что из этого является частным другого.

"Что говорит Google?"
Термины. Сразу конечно проблема с терминологией: по таким запросам как "voice chat" почему-то я в основном получаю ссылки на исходники по пересылке записанных аудио, т.е. не разговор в реальном времени, а как в современных мессенджерах предварительное записывание голоса с задерживанием кнопки микрофона. Если пишу "Интернет телефония" то тогда получаю ссылки по созданию приложений для звонка на мобильный телефон. Но мне не надо звонить на мобильный телефон, а необходимо связать два компьютера в интернете как это делает Skype и т.п.
P2P. Мне, я так понимаю лучше сразу обеспечить связь P2P между клиентами?
.NET. Как .NET разработчик мне конечно хочеться использовать в основе этот стек технологий или лучше использовать другой стек?
XMPP. Если можно так выразится, то часто предлагающее было использование для моих целей протокола XMPP (бывший Jabber).
SignalR. У меня есть небольшой опыт написание чата, где я использовал библиотеку SignalR и на мое удивление никто не предлагал использовать SignalR.

Вопрос
Если попытаться спросить конкретно без слов "с чего начать", то мой вопрос звучит так: Для начала мне бы хватил какой-нибудь маленький пример для разговора двух клиентов в локальной сети, ведь там у всех белые IP и скорость хорошая. Есть ли что-то готовое с чем я могу сделать прототип или библиотека/фреймворк с чего я могу менее безболезненно начать?


Ответ

Пример собственного велосипеда о котором ты спрашиваешь, можно найти здесь. В целом скоп задач, которые необходимо решить для разработки эффективной системы огромен, поэтому я бы на твоём месте смотрел исключительно в сторону готовых фреймворков. Большая часть из них строится на основе протокола SIP. Есть готовые коммерческие продукты, есть открытые и гибридные. Выбирай то, что тебе подходит и вперёд.

Выражение Assert при тестировании метода, который обновляет объект через сторонний сервис

Код
public class Company { public string Name { get; set; } }
public class Customer { public string Surname { get; set; } public string Name { get; set; } public Company Company { get; set; } }
public class CustomerDto { public int Id { get; set; }
[Required] public string Surname { get; set; }
[Required] public string Name { get; set; }
public string SecondName { get; set; } }
public class CustomerService { private readonly IGenericRepository _customerRepository;
public CustomerService(IGenericRepository customerRepository) { _customerRepository = customerRepository; }
public CustomerDto Add(CustomerDto dto) { //Validation if (dto == null) { throw new ArgumentNullException(nameof(dto)); } var validContext = new System.ComponentModel.DataAnnotations.ValidationContext(dto); Validator.ValidateObject(dto, validContext);
//Mapping by AutoMapper Mapper.Initialize(cfg => cfg.CreateMap()); var entity = Mapper.Map(dto);
_customerRepository.Insert(entity); _customerRepository.Save();
dto.Id = entity.Id;
return dto; } }

Юнит-тестирование CustomerService.Add()
Необходимо создать юнит-тест для метода Add(). Изначально, вообще была попытка реализовать этот метод через TDD, т.е. сначала создать для него юнит-тест и только затем имлемантацию. Но я не смог этого сделать так как не разобрался за что конкретно отвечает этот метод и надо ли вообще писать для него тест
Но два юнит-теста я сделал и вот как все это выглядит:
[TestClass] public class Customer_Test { [TestMethod] public void Add_Test() { //Arrange //Use NSubstitude for mocking var mockRepository = Substitute.For>();
//Act var service = new CustomerService(mockRepository); var dto = new CustomerDto { Surname = "Shakhabov", Name = "Adam" }; var addedDto = service.Add(dto);
//Assert Assert.IsNotNull(addedDto); }
[TestMethod] [ExpectedException(typeof(ValidationException))] public void Add_TestException() { //Arrange var mockRepository = Substitute.For>();
//Act var service = new CustomerService(mockRepository); var dto = new CustomerDto { Surname = "Shakhabov", }; var addedDto = service.Add(dto);
//Assert //expectedException ValidationException } }
Вот что (цель) должен сделать метод: Добавить в базу данных объект на основе полученного DTO-объекта и затем обратно вернуть этот DTO-объект, но уже с обновленным полем Id, значение для которого сформировала СУБД.
Вот как (задачи) делает это метод:
Получив DTO-объект, сразу верифицирует его; Используя библиотеку AutoMapper, проецирует DTO на сущность, которая в свою очередь создается с нуля; Используя объект-репозиторий, добавляет сущность в контекст. Сохраняет контекст в результате чего источник данных (СУБД) инициализирует поле Id у сущности (entity); Инициализирует поле dto.Id полем entity.Id и возвращает DTO.

Вопрос
Правильно ли были сформулированы требования для метода Add() и соответственно построены юнит-тесты на их основе? Какие тесты (выражения Assert) создаются для методов с подобной логикой, где целью является инициализировать свойство DTO-объекта значением, получаемое сторонним сервисом (в данном случаи объект-репозиторий)?


Ответ

Смотрим в метод Add. Что делает метод добавления? Добавляет новую сущность в БД и присваивает ей уникальный идентификатор.
С точки зрения возвращаемого значения - нужно вернуть только идентификатор, так как весь объект остался без изменений. Когда DTO приходит в метод добавления - идентификатор нулевой, то есть не заполнен. Когда сущьность (entity) будет добавлена в БД, ей будет присвоен новый уникальный идентифкатор. Так как используется тип данных int, то иднетификатор обязательно будет положительным (больше нуля) и уникален.
Конвертацию из DTO в объект сущности БД перенести внутрь DTO или добавить конструктор в сущность БД, который примет в качестве параметра DTO-шку. Про конвертацию подробнее: либо в объекте Customer сделать конструктор, который будет принимать объект типа CustomerDto, где внутри произвести присвоение полей с помощью AutoMapper, либо в CustomerDto сделать метод ToCustomer(), внутри которого создастся объект Customer и будут присвоены поля, который вернет объект типа Customer. Думаю, что с точки зрения логики, метод Add не должен делать эту конвертацию, так как его задача взять объект, добавить его и на основании результата уже будем знать, прошло ли все успешно.
Пример кода метода ToCustomer() в классе CustomerDto, для этого возможно понадобится подключить using для типа Customer и для AutoMapper, но это не беда, вот что я имел в виду:
public Customer ToCustomer() { //Mapping by AutoMapper Mapper.Initialize(cfg => cfg.CreateMap()); var entity = Mapper.Map(dto); return entity; }
По-хорошему и валидацию сделать бы более компактной и красивой, но это уже на ваше усмотрение. Еще один совет, инкапсулируйте в репозитрорий методы Insert и Save внутрь одного метода, который выполнит это (назовите его Create или Add). Ну и навесьте try...catch внутри метода, к примеру, если что-то пошло не так и упало исключение - тогда метод вернул -1, а в тестах вы уже будете знать, что если меньше нуля - то тест не прошел.
Касаемо тестов, у вас два сценария:
метод отработал успешно и без исключения - нужно проверить, что идентификатор не нулевой (больше нуля); пробуем подсунуть некорректные данные, которые вызовут исключение.
Соответственно, тестовый метод, проверяющий успешную работу должен проверить, что идентификатор не нулевой. Пример проверки: C# unit test, how to test greater than Там где ожидается исключение - не должно быть Assert проверок.
Касаемо TDD - это сложная практика, которая нарабатывается с опытом. Проще начать с написания простых классов через TDD, а потом уже переходить к более сложным сценариям. Чтобы писать через TDD, нужно иметь четкое представление того, как должна работать та или иная функциональность, которую вы хотите реализовать с ее помощью.
А еще, сейчас я занимаюсь приведением большого проекта в порядок с помощью одного вспомогательного компонента под названием StyleCop, так вот он не рекомендует использовать знак нижнего подчеркивания в именовании свойств, полей, параметров, переменных и прочего. Ну это так, к слову. Надеюсь, что мои советы и пояснения достаточно ясны и не вызовут противоречий.

Pandas изменение данных

Подскажите, в чём дело. Создаю DataFrame, хочу изменить значение, но ничего не выходит. В чём тут хитрость?
data = {'n':[1,1,1,1,1,1], 'bucket':['0','1-30','31-60','91-120','121-150','151-180'], 'balance':[1899.1644,1899.158,1741.408,1641.7814,1454.0343,1454.0343], 'date':['2016-01-16','2016-02-16','2016-03-16','2016-05-16','2016-06-16','2016-07-16']}
df = pd.DataFrame(data)
df.loc[5]['n']=100
Результат:

В маленьком примерчике такая же ерунда.
data = {'a':[1,2,3], 'b':['d','b','c']} df = pd.DataFrame(data) print(df) df.loc[0]['a'] = 100 print(df)

НО!!! Если числа, то всё ок:
data = {'a':[1,2,3], 'b':[5,6,7]} df = pd.DataFrame(data) print(df) df.loc[0]['a'] = 100 print(df)


Ответ

Pandas должен был выдать вам предупреждение (Warning), описывающее проблему:
In [7]: df.loc[5]['n']=100 C:\Users\Max\Anaconda4\Scripts\ipython3-script.py:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy if __name__ == '__main__':
In [8]: df Out[8]: balance bucket date n 0 1899.1644 0 2016-01-16 1 1 1899.1580 1-30 2016-02-16 1 2 1741.4080 31-60 2016-03-16 1 3 1641.7814 91-120 2016-05-16 1 4 1454.0343 121-150 2016-06-16 1 5 1454.0343 151-180 2016-07-16 1
Как это сделать правильно:
In [9]: df.loc[5, 'n'] = 100
In [10]: df Out[10]: balance bucket date n 0 1899.1644 0 2016-01-16 1 1 1899.1580 1-30 2016-02-16 1 2 1741.4080 31-60 2016-03-16 1 3 1641.7814 91-120 2016-05-16 1 4 1454.0343 121-150 2016-06-16 1 5 1454.0343 151-180 2016-07-16 100

Формирование std::tuple в C++11

Доброго времени суток, уважаемые.
У меня следующий вопрос:
Пусть есть шаблонный класс вот такого вида:
template class MyClass { public: using TupleT = std::tuple; ... private: TupleT m_tuple; };
и есть шаблонный класс
template WrapperT { ... };
Хочется сделать следующее: изменить тип m_tuple внутри MyClass с указанного выше на тип TupleWrappedT таким образом, что WrapperT будет выбирать по индексу элемент из TupleT и оборачивать его в себя. Вопрос, собственно, в том, как такой тип определить. Я придумал только
template using TupleWrappedT = std::tuple...>;
возможно ли обойтись без приставки template ? С учетом того, что элементы Is должны быть последовательны в диапазоне от 0 до sizeof...(Ts), а значит, известны на этапе компиляции.
Заранее благодарю за ответ.


Ответ

Держите :)
#include
template struct WrapperT {};
template static std::tuple...> wrap_impl(std::index_sequence);
template static auto wrap() -> decltype(wrap_impl(std::make_index_sequence::value>()));
template class MyClass { public: using TupleT = std::tuple; using TupleWrappedT = decltype(wrap()); private: TupleT m_tuple; };

int main() { static_assert(std::is_same::TupleT, std::tuple>::value, "!"); static_assert(std::is_same::TupleWrappedT, std::tuple>, WrapperT<1, std::tuple>>>::value, "!"); return 0; }

Как в javascript определять модели

в Java к примеру для каждого запроса и ответа создается POJO, где определяется поля которые будут в каком либо запросе или ответе, Принято ли такое создавать для Javascript, ведь это удобно.


Ответ

В Java так принято, потому что по другому долгое время было и невозможно (не знаю как сейчас). Кроме того в Java понятны собственно плюсы такого подхода, а именно строгая типизация обеспечивает проверку времени компиляции, поддержку со стороны IDE и т.п.
В JavaScript создание дополнительных классов в целом никак вам не поможет. Кроме того некоторыми людьми это воспринимается преимуществом, т.к. повышает скорость прототипирования и разработки, снижают "шум" в коде. Однако по мере возникновения типизированных надстроек типа TypeScript возникают и аналогичные практики.
В общем и целом в голом JavaScript скорее такой практики скорее нет, строгую валидацию и типизацию как правило оставляют на server-side.

Как изменить эл. почту автора во всём git-репозитории для всех снимков?

Как изменить эл. почту автора во всём git-репозитории для всех снимков?


Ответ

Как переписать всю историю с новым адресом почты.
Обратите внимание: коммиты нельзя редактировать, поэтому фактически это будет совершенно новая история. Переписывать историю может быть вредно, почитайте об этом подробнее
Для переписывания коммитов сразу и помногу в Git есть такая команда:
git filter-branch
Для удобства можно использовать вот такой git alias (автор — github.com/brauliobo). Он переписывает историю, меняя имя или адрес электронной почты автора.
Этой командой alias добавляется (выполните один раз):
git config --global alias.change-commits "!f() { VAR=$1; OLD=$2; NEW=$3; shift 3; git filter-branch --env-filter \"if [[ \\\"$`echo $VAR`\\\" = '$OLD' ]]; then export $VAR='$NEW'; fi\" $@; }; f "
Теперь можно менять автора так
git change-commits GIT_AUTHOR_NAME "старое имя" "новое имя"
Аналогично, почту:
git change-commits GIT_AUTHOR_EMAIL "old@email.com" "new@email.com"
Можно указать диапазон коммитов:
git change-commits GIT_AUTHOR_EMAIL "old@email.com" "new@email.com" HEAD~10..HEAD
(эта часть ответа написана на основе ответа на англоязычном SO)
Как узнавать автора по разным адресам электронной почты
Популярные git-хостинги (GitHub, GitLab, Bitbucket) позволяют добавить дополнительные адреса электропочты, по которым они будут распознавать ваши коммиты. Это имеет смысл, например, когда на рабочем месте для логина вы используете свою рабочую почту, а коммиты делаете с персональной почтой, чтобы не перенастраивать Git.
Возможно, вместо переписывания коммитов вам будет достаточно зарегистрировать почтовый адрес, указанный в коммитах, в интерфейсе вашего git-хостинга.
GitHub: Adding an email address to your GitHub account GitLab: Profile settings Bitbucket: Set email aliases

Работа с БД в сервисе

Можно ли работать с БД в сервисе? Дело вот в чем. Есть приложение которое берет аудио файл из assets и проигрывает его. Это все происходит в активити. А Названия этих файлов хранятся в БД. Думаю перенести всю логику плеера в сервис.
Поэтому вопрос.. Можно ли в сервисе работать с БД и AssetFileDescriptor?


Ответ

Да, никаких ограничений на работу с sqlite и assets в сервисе нет.

Анимация фона в FireFox

.backwrap { background: #113243; background-size:100% 100%; width:100%; height:100%; position:fixed; left:0; top:0; z-index:1; } /* Shapes & Animation */ .epic-icon { font-size:210%!important; opacity:0.5; display:inline-block; width:35px; height:35px; text-align:center; transition:0.3s all; } .back-shapes { width:100%; height:100%; position:relative; overflow:hidden; } .back-shapes img { opacity:0.2; position:absolute; width:2%; } .back-shapes em { opacity:0.2; position:absolute; width:2%; font-size:240%!important; color:#fff; } @media screen and (max-width: 1400px) { .back-shapes img { width:3%; } .back-shapes em { font-size:260%!important; } } @media screen and (max-width: 1000px) { .back-shapes img { width:4%; } .back-shapes em { font-size:230%!important; } } @media screen and (max-width: 600px) { .back-shapes img { width:5%; } .back-shapes em { font-size:180%!important; } } .floating{animation-name:floating;-webkit-animation-name:floating;-moz-animation-name:floating;animation-duration:5s;-webkit-animation-duration:5s;-moz-animation-duration:5s;animation-iteration-count:infinite;-webkit-animation-iteration-count:infinite;-moz-animation-iteration-count:infinite;} @keyframes floating{0%{transform:translateY(0%) rotate(-55deg);} 50%{transform:translateY(300%) rotate(55deg);} 100%{transform:translateY(0%) rotate(-55deg);} } @-webkit-keyframes floating{0%{-webkit-transform:translateY(0%);} 50%{-webkit-transform:translateY(300%);} 100%{-webkit-transform:translateY(0%);} } @-moz-keyframes floating{0%{-moz-transform:translateY(0%);} 50%{-moz-transform:translateY(300%);} 100%{-moz-transform:translateY(0%);} } /* Bootstrap's Grid */ .col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position: relative;min-height: 1px;padding-right: 15px;padding-left: 15px;} .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float: left;} .col-xs-12{width: 100%;} .col-xs-11{width: 91.66666667%;} .col-xs-10{width: 83.33333333%;} .col-xs-9{width: 75%;} .col-xs-8{width: 66.66666667%;} .col-xs-7{width: 58.33333333%;} .col-xs-6{width: 50%;} .col-xs-5{width: 41.66666667%;} .col-xs-4{width: 33.33333333%;} .col-xs-3{width: 25%;} .col-xs-2{width: 16.66666667%;} .col-xs-1{width: 8.33333333%;} .col-xs-pull-12{right: 100%;} .col-xs-pull-11{right: 91.66666667%;} .col-xs-pull-10{right: 83.33333333%;} .col-xs-pull-9{right: 75%;} .col-xs-pull-8{right: 66.66666667%;} .col-xs-pull-7{right: 58.33333333%;} .col-xs-pull-6{right: 50%;} .col-xs-pull-5{right: 41.66666667%;} .col-xs-pull-4{right: 33.33333333%;} .col-xs-pull-3{right: 25%;} .col-xs-pull-2{right: 16.66666667%;} .col-xs-pull-1{right: 8.33333333%;} .col-xs-pull-0{right: auto;} .col-xs-push-12{left: 100%;} .col-xs-push-11{left: 91.66666667%;} .col-xs-push-10{left: 83.33333333%;} .col-xs-push-9{left: 75%;} .col-xs-push-8{left: 66.66666667%;} .col-xs-push-7{left: 58.33333333%;} .col-xs-push-6{left: 50%;} .col-xs-push-5{left: 41.66666667%;} .col-xs-push-4{left: 33.33333333%;} .col-xs-push-3{left: 25%;} .col-xs-push-2{left: 16.66666667%;} .col-xs-push-1{left: 8.33333333%;} .col-xs-push-0{left: auto;} .col-xs-offset-12{margin-left: 100%;} .col-xs-offset-11{margin-left: 91.66666667%;} .col-xs-offset-10{margin-left: 83.33333333%;} .col-xs-offset-9{margin-left: 75%;} .col-xs-offset-8{margin-left: 66.66666667%;} .col-xs-offset-7{margin-left: 58.33333333%;} .col-xs-offset-6{margin-left: 50%;} .col-xs-offset-5{margin-left: 41.66666667%;} .col-xs-offset-4{margin-left: 33.33333333%;} .col-xs-offset-3{margin-left: 25%;} .col-xs-offset-2{margin-left: 16.66666667%;} .col-xs-offset-1{margin-left: 8.33333333%;} .col-xs-offset-0{margin-left: 0;} @media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float: left;} .col-sm-12{width: 100%;} .col-sm-11{width: 91.66666667%;} .col-sm-10{width: 83.33333333%;} .col-sm-9{width: 75%;} .col-sm-8{width: 66.66666667%;} .col-sm-7{width: 58.33333333%;} .col-sm-6{width: 50%;} .col-sm-5{width: 41.66666667%;} .col-sm-4{width: 33.33333333%;} .col-sm-3{width: 25%;} .col-sm-2{width: 16.66666667%;} .col-sm-1{width: 8.33333333%;} .col-sm-pull-12{right: 100%;} .col-sm-pull-11{right: 91.66666667%;} .col-sm-pull-10{right: 83.33333333%;} .col-sm-pull-9{right: 75%;} .col-sm-pull-8{right: 66.66666667%;} .col-sm-pull-7{right: 58.33333333%;} .col-sm-pull-6{right: 50%;} .col-sm-pull-5{right: 41.66666667%;} .col-sm-pull-4{right: 33.33333333%;} .col-sm-pull-3{right: 25%;} .col-sm-pull-2{right: 16.66666667%;} .col-sm-pull-1{right: 8.33333333%;} .col-sm-pull-0{right: auto;} .col-sm-push-12{left: 100%;} .col-sm-push-11{left: 91.66666667%;} .col-sm-push-10{left: 83.33333333%;} .col-sm-push-9{left: 75%;} .col-sm-push-8{left: 66.66666667%;} .col-sm-push-7{left: 58.33333333%;} .col-sm-push-6{left: 50%;} .col-sm-push-5{left: 41.66666667%;} .col-sm-push-4{left: 33.33333333%;} .col-sm-push-3{left: 25%;} .col-sm-push-2{left: 16.66666667%;} .col-sm-push-1{left: 8.33333333%;} .col-sm-push-0{left: auto;} .col-sm-offset-12{margin-left: 100%;} .col-sm-offset-11{margin-left: 91.66666667%;} .col-sm-offset-10{margin-left: 83.33333333%;} .col-sm-offset-9{margin-left: 75%;} .col-sm-offset-8{margin-left: 66.66666667%;} .col-sm-offset-7{margin-left: 58.33333333%;} .col-sm-offset-6{margin-left: 50%;} .col-sm-offset-5{margin-left: 41.66666667%;} .col-sm-offset-4{margin-left: 33.33333333%;} .col-sm-offset-3{margin-left: 25%;} .col-sm-offset-2{margin-left: 16.66666667%;} .col-sm-offset-1{margin-left: 8.33333333%;} .col-sm-offset-0{margin-left: 0;} } @media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float: left;} .col-md-12{width: 100%;} .col-md-11{width: 91.66666667%;} .col-md-10{width: 83.33333333%;} .col-md-9{width: 75%;} .col-md-8{width: 66.66666667%;} .col-md-7{width: 58.33333333%;} .col-md-6{width: 50%;} .col-md-5{width: 41.66666667%;} .col-md-4{width: 33.33333333%;} .col-md-3{width: 25%;} .col-md-2{width: 16.66666667%;} .col-md-1{width: 8.33333333%;} .col-md-pull-12{right: 100%;} .col-md-pull-11{right: 91.66666667%;} .col-md-pull-10{right: 83.33333333%;} .col-md-pull-9{right: 75%;} .col-md-pull-8{right: 66.66666667%;} .col-md-pull-7{right: 58.33333333%;} .col-md-pull-6{right: 50%;} .col-md-pull-5{right: 41.66666667%;} .col-md-pull-4{right: 33.33333333%;} .col-md-pull-3{right: 25%;} .col-md-pull-2{right: 16.66666667%;} .col-md-pull-1{right: 8.33333333%;} .col-md-pull-0{right: auto;} .col-md-push-12{left: 100%;} .col-md-push-11{left: 91.66666667%;} .col-md-push-10{left: 83.33333333%;} .col-md-push-9{left: 75%;} .col-md-push-8{left: 66.66666667%;} .col-md-push-7{left: 58.33333333%;} .col-md-push-6{left: 50%;} .col-md-push-5{left: 41.66666667%;} .col-md-push-4{left: 33.33333333%;} .col-md-push-3{left: 25%;} .col-md-push-2{left: 16.66666667%;} .col-md-push-1{left: 8.33333333%;} .col-md-push-0{left: auto;} .col-md-offset-12{margin-left: 100%;} .col-md-offset-11{margin-left: 91.66666667%;} .col-md-offset-10{margin-left: 83.33333333%;} .col-md-offset-9{margin-left: 75%;} .col-md-offset-8{margin-left: 66.66666667%;} .col-md-offset-7{margin-left: 58.33333333%;} .col-md-offset-6{margin-left: 50%;} .col-md-offset-5{margin-left: 41.66666667%;} .col-md-offset-4{margin-left: 33.33333333%;} .col-md-offset-3{margin-left: 25%;} .col-md-offset-2{margin-left: 16.66666667%;} .col-md-offset-1{margin-left: 8.33333333%;} .col-md-offset-0{margin-left: 0;} } @media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float: left;} .col-lg-12{width: 100%;} .col-lg-11{width: 91.66666667%;} .col-lg-10{width: 83.33333333%;} .col-lg-9{width: 75%;} .col-lg-8{width: 66.66666667%;} .col-lg-7{width: 58.33333333%;} .col-lg-6{width: 50%;} .col-lg-5{width: 41.66666667%;} .col-lg-4{width: 33.33333333%;} .col-lg-3{width: 25%;} .col-lg-2{width: 16.66666667%;} .col-lg-1{width: 8.33333333%;} .col-lg-pull-12{right: 100%;} .col-lg-pull-11{right: 91.66666667%;} .col-lg-pull-10{right: 83.33333333%;} .col-lg-pull-9{right: 75%;} .col-lg-pull-8{right: 66.66666667%;} .col-lg-pull-7{right: 58.33333333%;} .col-lg-pull-6{right: 50%;} .col-lg-pull-5{right: 41.66666667%;} .col-lg-pull-4{right: 33.33333333%;} .col-lg-pull-3{right: 25%;} .col-lg-pull-2{right: 16.66666667%;} .col-lg-pull-1{right: 8.33333333%;} .col-lg-pull-0{right: auto;} .col-lg-push-12{left: 100%;} .col-lg-push-11{left: 91.66666667%;} .col-lg-push-10{left: 83.33333333%;} .col-lg-push-9{left: 75%;} .col-lg-push-8{left: 66.66666667%;} .col-lg-push-7{left: 58.33333333%;} .col-lg-push-6{left: 50%;} .col-lg-push-5{left: 41.66666667%;} .col-lg-push-4{left: 33.33333333%;} .col-lg-push-3{left: 25%;} .col-lg-push-2{left: 16.66666667%;} .col-lg-push-1{left: 8.33333333%;} .col-lg-push-0{left: auto;} .col-lg-offset-12{margin-left: 100%;} .col-lg-offset-11{margin-left: 91.66666667%;} .col-lg-offset-10{margin-left: 83.33333333%;} .col-lg-offset-9{margin-left: 75%;} .col-lg-offset-8{margin-left: 66.66666667%;} .col-lg-offset-7{margin-left: 58.33333333%;} .col-lg-offset-6{margin-left: 50%;} .col-lg-offset-5{margin-left: 41.66666667%;} .col-lg-offset-4{margin-left: 33.33333333%;} .col-lg-offset-3{margin-left: 25%;} .col-lg-offset-2{margin-left: 16.66666667%;} .col-lg-offset-1{margin-left: 8.33333333%;} .col-lg-offset-0{margin-left: 0;} }


Нашёл на просторах интернета одну интересную задумку с фоном, довёл её до ума, но наткнулся на одну проблему с которой бьюсь уже день... Проблема в том что в Chrome анимация работает как надо, но в FireFox не полностью (не вращаются иконки) Прошу помочь или объясните что делаю не так)


Ответ

У вас в keyframes для -moz- и -webkit- не прописана анимация вращения, вот они и не вращаются.
.backwrap { background: #113243; background-size: 100% 100%; width: 100%; height: 100%; position: fixed; left: 0; top: 0; z-index: 1; } /* Shapes & Animation */ .epic-icon { font-size: 210%!important; opacity: 0.5; display: inline-block; width: 35px; height: 35px; text-align: center; transition: 0.3s all; } .back-shapes { width: 100%; height: 100%; position: relative; overflow: hidden; } .back-shapes img { opacity: 0.2; position: absolute; width: 2%; } .back-shapes em { opacity: 0.2; position: absolute; width: 2%; font-size: 240%!important; color: #fff; } @media screen and (max-width: 1400px) { .back-shapes img { width: 3%; } .back-shapes em { font-size: 260%!important; } } @media screen and (max-width: 1000px) { .back-shapes img { width: 4%; } .back-shapes em { font-size: 230%!important; } } @media screen and (max-width: 600px) { .back-shapes img { width: 5%; } .back-shapes em { font-size: 180%!important; } } .floating { animation-name: floating; -webkit-animation-name: floating; -moz-animation-name: floating; animation-duration: 5s; -webkit-animation-duration: 5s; -moz-animation-duration: 5s; animation-iteration-count: infinite; -webkit-animation-iteration-count: infinite; -moz-animation-iteration-count: infinite; } @keyframes floating { 0% { transform: translateY(0%) rotate(-55deg); } 50% { transform: translateY(300%) rotate(55deg); } 100% { transform: translateY(0%) rotate(-55deg); } } @-webkit-keyframes floating { 0% { -webkit-transform: translateY(0%) rotate(-55deg); } 50% { -webkit-transform: translateY(300%) rotate(55deg); } 100% { -webkit-transform: translateY(0%) rotate(-55deg); } } @-moz-keyframes floating { 0% { -moz-transform: translateY(0%) rotate(-55deg); } 50% { -moz-transform: translateY(300%) rotate(55deg); } 100% { -moz-transform: transform: translateY(0%) rotate(-55deg); } } /* Bootstrap's Grid */ .col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { position: relative; min-height: 1px; padding-right: 15px; padding-left: 15px; } .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { float: left; } .col-xs-12 { width: 100%; } .col-xs-11 { width: 91.66666667%; } .col-xs-10 { width: 83.33333333%; } .col-xs-9 { width: 75%; } .col-xs-8 { width: 66.66666667%; } .col-xs-7 { width: 58.33333333%; } .col-xs-6 { width: 50%; } .col-xs-5 { width: 41.66666667%; } .col-xs-4 { width: 33.33333333%; } .col-xs-3 { width: 25%; } .col-xs-2 { width: 16.66666667%; } .col-xs-1 { width: 8.33333333%; } .col-xs-pull-12 { right: 100%; } .col-xs-pull-11 { right: 91.66666667%; } .col-xs-pull-10 { right: 83.33333333%; } .col-xs-pull-9 { right: 75%; } .col-xs-pull-8 { right: 66.66666667%; } .col-xs-pull-7 { right: 58.33333333%; } .col-xs-pull-6 { right: 50%; } .col-xs-pull-5 { right: 41.66666667%; } .col-xs-pull-4 { right: 33.33333333%; } .col-xs-pull-3 { right: 25%; } .col-xs-pull-2 { right: 16.66666667%; } .col-xs-pull-1 { right: 8.33333333%; } .col-xs-pull-0 { right: auto; } .col-xs-push-12 { left: 100%; } .col-xs-push-11 { left: 91.66666667%; } .col-xs-push-10 { left: 83.33333333%; } .col-xs-push-9 { left: 75%; } .col-xs-push-8 { left: 66.66666667%; } .col-xs-push-7 { left: 58.33333333%; } .col-xs-push-6 { left: 50%; } .col-xs-push-5 { left: 41.66666667%; } .col-xs-push-4 { left: 33.33333333%; } .col-xs-push-3 { left: 25%; } .col-xs-push-2 { left: 16.66666667%; } .col-xs-push-1 { left: 8.33333333%; } .col-xs-push-0 { left: auto; } .col-xs-offset-12 { margin-left: 100%; } .col-xs-offset-11 { margin-left: 91.66666667%; } .col-xs-offset-10 { margin-left: 83.33333333%; } .col-xs-offset-9 { margin-left: 75%; } .col-xs-offset-8 { margin-left: 66.66666667%; } .col-xs-offset-7 { margin-left: 58.33333333%; } .col-xs-offset-6 { margin-left: 50%; } .col-xs-offset-5 { margin-left: 41.66666667%; } .col-xs-offset-4 { margin-left: 33.33333333%; } .col-xs-offset-3 { margin-left: 25%; } .col-xs-offset-2 { margin-left: 16.66666667%; } .col-xs-offset-1 { margin-left: 8.33333333%; } .col-xs-offset-0 { margin-left: 0; } @media (min-width:768px) { .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { float: left; } .col-sm-12 { width: 100%; } .col-sm-11 { width: 91.66666667%; } .col-sm-10 { width: 83.33333333%; } .col-sm-9 { width: 75%; } .col-sm-8 { width: 66.66666667%; } .col-sm-7 { width: 58.33333333%; } .col-sm-6 { width: 50%; } .col-sm-5 { width: 41.66666667%; } .col-sm-4 { width: 33.33333333%; } .col-sm-3 { width: 25%; } .col-sm-2 { width: 16.66666667%; } .col-sm-1 { width: 8.33333333%; } .col-sm-pull-12 { right: 100%; } .col-sm-pull-11 { right: 91.66666667%; } .col-sm-pull-10 { right: 83.33333333%; } .col-sm-pull-9 { right: 75%; } .col-sm-pull-8 { right: 66.66666667%; } .col-sm-pull-7 { right: 58.33333333%; } .col-sm-pull-6 { right: 50%; } .col-sm-pull-5 { right: 41.66666667%; } .col-sm-pull-4 { right: 33.33333333%; } .col-sm-pull-3 { right: 25%; } .col-sm-pull-2 { right: 16.66666667%; } .col-sm-pull-1 { right: 8.33333333%; } .col-sm-pull-0 { right: auto; } .col-sm-push-12 { left: 100%; } .col-sm-push-11 { left: 91.66666667%; } .col-sm-push-10 { left: 83.33333333%; } .col-sm-push-9 { left: 75%; } .col-sm-push-8 { left: 66.66666667%; } .col-sm-push-7 { left: 58.33333333%; } .col-sm-push-6 { left: 50%; } .col-sm-push-5 { left: 41.66666667%; } .col-sm-push-4 { left: 33.33333333%; } .col-sm-push-3 { left: 25%; } .col-sm-push-2 { left: 16.66666667%; } .col-sm-push-1 { left: 8.33333333%; } .col-sm-push-0 { left: auto; } .col-sm-offset-12 { margin-left: 100%; } .col-sm-offset-11 { margin-left: 91.66666667%; } .col-sm-offset-10 { margin-left: 83.33333333%; } .col-sm-offset-9 { margin-left: 75%; } .col-sm-offset-8 { margin-left: 66.66666667%; } .col-sm-offset-7 { margin-left: 58.33333333%; } .col-sm-offset-6 { margin-left: 50%; } .col-sm-offset-5 { margin-left: 41.66666667%; } .col-sm-offset-4 { margin-left: 33.33333333%; } .col-sm-offset-3 { margin-left: 25%; } .col-sm-offset-2 { margin-left: 16.66666667%; } .col-sm-offset-1 { margin-left: 8.33333333%; } .col-sm-offset-0 { margin-left: 0; } } @media (min-width:992px) { .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { float: left; } .col-md-12 { width: 100%; } .col-md-11 { width: 91.66666667%; } .col-md-10 { width: 83.33333333%; } .col-md-9 { width: 75%; } .col-md-8 { width: 66.66666667%; } .col-md-7 { width: 58.33333333%; } .col-md-6 { width: 50%; } .col-md-5 { width: 41.66666667%; } .col-md-4 { width: 33.33333333%; } .col-md-3 { width: 25%; } .col-md-2 { width: 16.66666667%; } .col-md-1 { width: 8.33333333%; } .col-md-pull-12 { right: 100%; } .col-md-pull-11 { right: 91.66666667%; } .col-md-pull-10 { right: 83.33333333%; } .col-md-pull-9 { right: 75%; } .col-md-pull-8 { right: 66.66666667%; } .col-md-pull-7 { right: 58.33333333%; } .col-md-pull-6 { right: 50%; } .col-md-pull-5 { right: 41.66666667%; } .col-md-pull-4 { right: 33.33333333%; } .col-md-pull-3 { right: 25%; } .col-md-pull-2 { right: 16.66666667%; } .col-md-pull-1 { right: 8.33333333%; } .col-md-pull-0 { right: auto; } .col-md-push-12 { left: 100%; } .col-md-push-11 { left: 91.66666667%; } .col-md-push-10 { left: 83.33333333%; } .col-md-push-9 { left: 75%; } .col-md-push-8 { left: 66.66666667%; } .col-md-push-7 { left: 58.33333333%; } .col-md-push-6 { left: 50%; } .col-md-push-5 { left: 41.66666667%; } .col-md-push-4 { left: 33.33333333%; } .col-md-push-3 { left: 25%; } .col-md-push-2 { left: 16.66666667%; } .col-md-push-1 { left: 8.33333333%; } .col-md-push-0 { left: auto; } .col-md-offset-12 { margin-left: 100%; } .col-md-offset-11 { margin-left: 91.66666667%; } .col-md-offset-10 { margin-left: 83.33333333%; } .col-md-offset-9 { margin-left: 75%; } .col-md-offset-8 { margin-left: 66.66666667%; } .col-md-offset-7 { margin-left: 58.33333333%; } .col-md-offset-6 { margin-left: 50%; } .col-md-offset-5 { margin-left: 41.66666667%; } .col-md-offset-4 { margin-left: 33.33333333%; } .col-md-offset-3 { margin-left: 25%; } .col-md-offset-2 { margin-left: 16.66666667%; } .col-md-offset-1 { margin-left: 8.33333333%; } .col-md-offset-0 { margin-left: 0; } } @media (min-width:1200px) { .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { float: left; } .col-lg-12 { width: 100%; } .col-lg-11 { width: 91.66666667%; } .col-lg-10 { width: 83.33333333%; } .col-lg-9 { width: 75%; } .col-lg-8 { width: 66.66666667%; } .col-lg-7 { width: 58.33333333%; } .col-lg-6 { width: 50%; } .col-lg-5 { width: 41.66666667%; } .col-lg-4 { width: 33.33333333%; } .col-lg-3 { width: 25%; } .col-lg-2 { width: 16.66666667%; } .col-lg-1 { width: 8.33333333%; } .col-lg-pull-12 { right: 100%; } .col-lg-pull-11 { right: 91.66666667%; } .col-lg-pull-10 { right: 83.33333333%; } .col-lg-pull-9 { right: 75%; } .col-lg-pull-8 { right: 66.66666667%; } .col-lg-pull-7 { right: 58.33333333%; } .col-lg-pull-6 { right: 50%; } .col-lg-pull-5 { right: 41.66666667%; } .col-lg-pull-4 { right: 33.33333333%; } .col-lg-pull-3 { right: 25%; } .col-lg-pull-2 { right: 16.66666667%; } .col-lg-pull-1 { right: 8.33333333%; } .col-lg-pull-0 { right: auto; } .col-lg-push-12 { left: 100%; } .col-lg-push-11 { left: 91.66666667%; } .col-lg-push-10 { left: 83.33333333%; } .col-lg-push-9 { left: 75%; } .col-lg-push-8 { left: 66.66666667%; } .col-lg-push-7 { left: 58.33333333%; } .col-lg-push-6 { left: 50%; } .col-lg-push-5 { left: 41.66666667%; } .col-lg-push-4 { left: 33.33333333%; } .col-lg-push-3 { left: 25%; } .col-lg-push-2 { left: 16.66666667%; } .col-lg-push-1 { left: 8.33333333%; } .col-lg-push-0 { left: auto; } .col-lg-offset-12 { margin-left: 100%; } .col-lg-offset-11 { margin-left: 91.66666667%; } .col-lg-offset-10 { margin-left: 83.33333333%; } .col-lg-offset-9 { margin-left: 75%; } .col-lg-offset-8 { margin-left: 66.66666667%; } .col-lg-offset-7 { margin-left: 58.33333333%; } .col-lg-offset-6 { margin-left: 50%; } .col-lg-offset-5 { margin-left: 41.66666667%; } .col-lg-offset-4 { margin-left: 33.33333333%; } .col-lg-offset-3 { margin-left: 25%; } .col-lg-offset-2 { margin-left: 16.66666667%; } .col-lg-offset-1 { margin-left: 8.33333333%; } .col-lg-offset-0 { margin-left: 0; } }


Аналог `element.style.left = variable + 'px'`, только без 'px'

Имеется элемент:
let element = document.getElementById('id')
Я могу изменить его css-свойство left вот так:
let left = ... highlight.style.left = left + 'px';
Есть ли аналог этого, только без необходимости писать 'px'?

Например, с помощью jquery можно так:
$(element).css('left', left);
А можно без jquery (и без 'px')?


Ответ

Да. Нет. Нет.
Хотя ну ладно, на последний вопрос - да:
var $ = (function () { var allowNumber = ['lineHeight', 'zIndex']; function $(el) { if (this instanceof $) { this.el = el; } else { return new $(el); } } $.prototype.css = function css(key, value) { key = key.replace(/-(\w)/g, function (m, ch) { return ch.toUpperCase() }); if (+value == value && allowNumber.indexOf(key) === -1) { value += 'px'; } this.el.style[key] = value; return this; } return $; })(); $(document.querySelector("div")).css('left', 100).css('line-height', 3); div { position: absolute; left: 0; top: 0; background: silver; }

123

PS: Пиксели - зло.

Параметры загрузки ядра Linux(Ubuntu)

Здравствуйте, сразу оговорюсь новичок в использовании линукса, поэтому прошу выражаться как можно свободнее.
Установил ubuntu с флешки, при запуске компьютера появляется grub меню, в котором выбираю запустить ubuntu, после этого фиолетовый экран(продолжает висеть бесконечно), на некоторых форумах прочитал о проблеме с acpi, и что в grub меню надо открыть параметры загрузки ядра и устанавливать параметры для корректной работы acpi. У меня ноутбук Acer Swift 3(Core i3-6100U, 4gb RAM, Intel HD Graphics 520).
Примечание: один раз систему удалось запустить указав параметры: (pci=noacpi, acpi=noirq, pnpacpi=off). Очень много гуглил не могу найти хороших источников, буду рад любой помощи. Версия ubuntu 16.04.3


Ответ

Подобная проблема была на Acer Aspire E3, вылечить получилось следующим образом:
Загрузка системы с параметром acpi=noirq Редактирую /etc/default/grub sudo nano /etc/default/grub Меняем GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" на GRUB_CMDLINE_LINUX_DEFAULT="acpi=noirq" Сохраняю файл. Обновлем параметры загрузчика sudo update-grub Перезагружаемся. После этого загрузка системы не такая "красивая", но включается/выключается без проблем

Выборка объектов массива с их последующей вставкой в разметку страницы

Господа, прошу помощи, ибо никак не могу организовать логику скрипта, который находил бы нужные объекты и вставлял их в разметку. Подробности ниже.
Есть таблица календаря, которая генерится а js, есть массив объектов, каждый объект хранит в себе информацию о годе+месяце (year), дне месяца (day), событии (event), остальные параметры не так важны. Нужен скрипт, который будет пробегать по массиву, сверять месяц+год календаря с месяцем+годом в объектах, если все совпадает, то далее пробегать по таблице и сверять день календаря с днями в объектах, если совпадает, то в ячейку с совпадающей датой добавлять div с event, хранящимся в объекте.
Сейчас происходит почти то что нужно, НО если в массиве есть несколько объектов с совпадающими day объекта и днем календаря, то в ячейку с датой добавляется ТОЛЬКО первый объект, остальные игнорируются.
Вот так это выглядит сейчас:
let arr = [{ dateEvent: "Первый тест", day: "11", description: "Первый тест", event: "Первый тест", names: "Первый тест", year: "Октябрь 2017" }, { dateEvent: "Второй тест", day: "11", description: "Первый тест", event: "Первый тест", names: "Первый тест", year: "Октябрь 2017" }, { dateEvent: "Третий тест", day: "11", description: "Первый тест", event: "Первый тест", names: "Первый тест", year: "Октябрь 2017" }, { dateEvent: "Четвертый тест", day: "10", description: "Первый тест", event: "Первый тест", names: "Первый тест", year: "Октябрь 2017" }, ] const showAllEvents = () => { let arrEvents = arr, list = document.getElementById("organizer").getElementsByTagName('td'); //берем первый день - внешний цикл for (let j = 0; j < list.length; j++) { //первый объект в массиве - внутренний цикл for (let i = 0; i < arrEvents.length; i++) { //проверяем соответсвие месяца и года с данными в объекте if (document.getElementById('year').innerHTML === arrEvents[i].year) { //проверяем день календаря и день объекта if (list[j].innerHTML === arrEvents[i].day) { //тут слайсится Событие let text = arrEvents[i].event, slicedEvent = text.slice(0, 15); if (slicedEvent.length < text.length) { slicedEvent += '...'; } //создаем див, в него вставляем дивы с данными, которые должны хранится в ячейке let appendDiv = document.createElement('div'); appendDiv.className = 'event-div'; appendDiv.innerHTML = `

` + slicedEvent + `
`; //вставляем этот див в текущую ячейку document.getElementsByTagName('td')[j].appendChild(appendDiv); } //как я понимаю, внутренний цикл должен повториться и перейти ко второму объекту, //но почему-то вместо этого сразу начинается новая итерация внешнего цикла } } } }; showAllEvents(); body { width: 100%; height: 100%; margin: 0; padding: 0; position: relative; z-index: 333; } #calendar { width: 80%; height: 90%; margin: 0 auto; } #control-month span:first-child, #control-month span:last-child { cursor: pointer; } #control-month div { cursor: pointer; } #organizer { border-collapse: collapse; width: 100%; font-family: monospace; line-height: 1.2em; font-size: 15px; text-align: center; word-break: break-all; table-layout: fixed; } #organizer thead { color: rgb(50, 50, 50); font-size: 10px; } #organizer tbody tr { height: 80px; } #organizer tbody td { position: relative; color: rgb(44, 86, 122); font-size: 10px; vertical-align: top; cursor: pointer; border: 1px solid dimgrey; z-index: 33; } #organizer tbody td:nth-child(n+6), #organizer .holiday { color: rgb(231, 140, 92); } #organizer tbody td.today { background: rgb(220, 0, 0); color: #fff; } #cover-div { width: 15%; height: 25%; position: absolute; background: lightsteelblue; border: 1px solid darkgray; } #cover-div input, #cover-div textarea { box-sizing: border-box; } #overlay-div { width: 100%; height: 100%; top: 0; left: 0; position: fixed; } Title
Октябрь 2017
Сегодня
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          

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


Ответ

Проблема в том, что вы сравниваете list[j].innerHTML === arrEvents[i].day. После первого успешного совпадения list[j].innerHTML уже не будет только текст 11, потому что вы добавляете туда несколько новых элементов document.getElementsByTagName('td')[j].appendChild(appendDiv);.
Для обхода этой ситуации можно хранить данные в data-* атрибутах элемента. Вообще, лучше данные хранить там, и по возможности стараться избегать сравнений вида list[j].innerHTML === arrEvents[i].day
Пример работающего кода.
let arr = [{ dateEvent: "Первый тест", day: "11", description: "Первый тест", event: "Первый тест", names: "Первый тест", year: "Октябрь 2017" }, { dateEvent: "Второй тест", day: "11", description: "Первый тест", event: "Второй тест", names: "Первый тест", year: "Октябрь 2017" }, { dateEvent: "Третий тест", day: "11", description: "Первый тест", event: "Третий тест", names: "Первый тест", year: "Октябрь 2017" }, { dateEvent: "Четвертый тест", day: "10", description: "Первый тест", event: "Четвертый тест", names: "Первый тест", year: "Октябрь 2017" }, ] const showAllEvents = () => { let arrEvents = arr, list = document.getElementById("organizer").getElementsByTagName('td'), year = document.getElementById('year'); //берем первый день - внешний цикл for (let j = 0; j < list.length; j++) { let td = list[j]; //первый объект в массиве - внутренний цикл for (let i = 0; i < arrEvents.length; i++) { let event = arrEvents[i]; //проверяем соответсвие месяца и года с данными в объекте if (year.innerHTML === event.year) { //проверяем день календаря и день объекта if (td.getAttribute("data-day") === event.day) { //тут слайсится Событие let text = event.event, slicedEvent = text.slice(0, 15); if (slicedEvent.length < text.length) { slicedEvent += '...'; } //создаем див, в него вставляем дивы с данными, которые должны хранится в ячейке let appendDiv = document.createElement('div'); appendDiv.className = 'event-div'; appendDiv.innerHTML = `

` + slicedEvent + `
`; //вставляем этот див в текущую ячейку //document.getElementsByTagName('td')[j].appendChild(appendDiv); td.appendChild(appendDiv); // эквивалетно } //как я понимаю, внутренний цикл должен повториться и перейти ко второму объекту, //но почему-то вместо этого сразу начинается новая итерация внешнего цикла } } } }; showAllEvents(); body { width: 100%; height: 100%; margin: 0; padding: 0; position: relative; z-index: 333; } #calendar { width: 80%; height: 90%; margin: 0 auto; } #control-month span:first-child, #control-month span:last-child { cursor: pointer; } #control-month div { cursor: pointer; } #organizer { border-collapse: collapse; width: 100%; font-family: monospace; line-height: 1.2em; font-size: 15px; text-align: center; word-break: break-all; table-layout: fixed; } #organizer thead { color: rgb(50, 50, 50); font-size: 10px; } #organizer tbody tr { height: 80px; } #organizer tbody td { position: relative; color: rgb(44, 86, 122); font-size: 10px; vertical-align: top; cursor: pointer; border: 1px solid dimgrey; z-index: 33; } #organizer tbody td:nth-child(n+6), #organizer .holiday { color: rgb(231, 140, 92); } #organizer tbody td.today { background: rgb(220, 0, 0); color: #fff; } #cover-div { width: 15%; height: 25%; position: absolute; background: lightsteelblue; border: 1px solid darkgray; } #cover-div input, #cover-div textarea { box-sizing: border-box; } #overlay-div { width: 100%; height: 100%; top: 0; left: 0; position: fixed; } Title
Октябрь 2017
Сегодня
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          

P.S. Также немного отрефакторил ваш код.