Задать вопрос
  • Как грамотно организовать хранение исходного кода и сборку NuGet-пакетов в Gitlab?

    @d-stream
    Готовые решения - не подаю, но...
    Ну хранить бинарные это в гитлабе - по мне не самая лучшая идея. Идеологически пакеты - это результаты а не исходный материал. Как один из вариантов - использовать внешнее хранилище. К примеру sonatype nexus. Притом он умеет и не только в .nuget. Бонусом - его умение полноценно поддерживать nuget-api. То есть не возникнет вопросов при использовании пакетов и восстановлении транзитивных зависимостей.
    Конечно в .nuspec можно и нужно заполнять честно Видимо да, корнем будет Company или нечто подобное для группы компаний.
    Дальше видимо отдельная ветвь нечто совсем общего для всех продуктов со своим ветвлением на lib/utils/helpers/etc и ветвления на продукты, где далее опять же нечто общее для всех версий и далее ветвление по версиям и дальше уже опять же modules/libs/utils

    (кстати внутреннюю делёжку можно подсмотреть со стороны самой структуры дерева в nuget (рекомендуемая структура target от ms)

    То бишь в итоге получится нечто типа такого:
    Brand
     - CommonBrandSubTree
       - *
     - Subbrands
       - SubbrandsCommon
         - * 
         - ProductX 
           - ProductCommon
           - *
         - ProductY 
           - ProductCommon
           - *
    ________
    * - это то самое lib/tools/frameworks/etc


    Притом не стоит бояться слишком разветвлённого дерева - хотя на первом этапе это и будет выглядеть чрезмерно переинженеренным. Зато потом не придётся его ломать и ветвить на ходу.

    Ну а смысл в общем-то есть: у среднего человека мгновенная память/восприятие способна охватить "за раз" 5-9 объектов и исходя из этого максимально комфортной структурой окажется дерево, где на каждом уровне будет видно где-то по 5-9 объектов.

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

    с длиной имён путей/файлов - да можно огрести чуть дальше - на уровне сборки - win-раннеры не умеют в \\?\driveletter и воспользоваться вариантом длины пути в 32767 символов не выйдет...

    p.s. ну и по-любому морально стоит готовиться к какому-то кардинальному моменту, когда захочется начать новое дерево с нуля - этакую v.2.0 (возможно стартовав такое уже в другой компании))
    Ответ написан
    Комментировать
  • Определить победителя КНБ?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    (-1) % 3 = 2

    Это математическое определение вычетов по модулю. Все числа, которые отличаются на n, имеют одинаковый остаток по модулю n. Конфуз происходит из-за того, что операция взятия по модулю во многих языках программирования работает не так. Для отрицательных чисел она выдаст отрицательное значение, правда к которому можно прибавить n, что бы получить правильный модуль - число от 0 до n-1.

    Поэтому при реализации можно делать (a-b+3)%3 Или преобразовать, чтобы не было вычитания: b == (a+1)%3
    Ответ написан
    Комментировать
  • Как эффективно найти все объекты, у которых в названии есть все заданные слова?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Тут же можно за один проход по магазинам. Сначала пройдитесь по вашим комбинациям и сложите слова в хешмап "слово" -> список номеров пар, в которых оно есть.

    Потом для каждого магазина пометьте массив длиной сколько у вас пар тегов нулями. Потом по каждому слову пройдитесь и добавьте 1 к каждой паре в массив, в которой это слово всречается, используя мап из предыдущего пункта. Если где-то получили 2 в процессе, то этот магазин вам подходит.

    Если же вы можете один раз что-то предподсчитать для всех магазинов, то потом можно выполнять "запросы" даже не проходясь по всем магазинам.

    Можно по каждому тегу составить список магазинов, имеющих его в названии, упорядоченный как-то (допустим, по id магазинов). Эту структуру можно построить за один проход по всем магазинам и сохранить.

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

    В хужшем случае, где используется очень частый тег, обработка запроса будет почти как полный просмотр всех магазинов (даже если в ответ попадет их малая часть), но в среднем этот метод будет работать неплохо.
    Ответ написан
    Комментировать
  • Как эффективно найти все объекты, у которых в названии есть все заданные слова?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Конечно, есть. Можно увеличить скорость за счёт использования памяти.

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

    Если подумать, можно ещё что-нибудь наоптимизировать. Но это уже надо знать больше нюансов конкретно вашей задачи.
    Ответ написан
    Комментировать
  • Можно ли сделать вызов переменной защиты private через get; set?

    firedragon
    @firedragon
    Не джун-мидл-сеньор, а трус-балбес-бывалый.
    с помошью рефлексии можно сделать много. но зачем?
    Ответ написан
    Комментировать
  • Можно ли сделать вызов переменной защиты private через get; set?

    iversooon
    @iversooon
    Учу C# и вообще все, но все равно ничего не знаю
    если тебе нужно ограничить запись, тогда лучше так:
    public string Name { get; private set; }
    Ответ написан
    Комментировать
  • Выводит что y = ?, как исправить?

    x = -3.5308641975308643, y = -∞, z =93.25781896015157, r = 0.4

    "y" имеет значение "минус бесконечность"
    У вас просто в используемом шрифте нет нужного символа.
    Как исправить - фиг знает.
    Может у вас ошибка в формуле.
    Если это норма - просто проверяйте, является ли ваше число бесконечностью при помощи метода Double.IsInfinity, Double.IsPositiveInfinity, Double.IsNegativeInfinity
    Ответ написан
    5 комментариев
  • Как изменить приоритет действующего процесса из списка диспетчера задач?

    Любой подобный вопрос нужно решать, начиная с того, как это нативный API делается:
    https://docs.microsoft.com/en-us/windows/win32/api...
    А вот как вызывать подобные нативные функции:
    https://docs.microsoft.com/en-us/dotnet/standard/n...
    Таким образом, можно сделать вот так:
    [DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
    public static extern bool SetPriorityClass(IntPtr handle, PriorityClass priorityClass);
    public enum PriorityClass : uint
    {
           ABOVE_NORMAL_PRIORITY_CLASS = 0x8000,
           BELOW_NORMAL_PRIORITY_CLASS = 0x4000,
           HIGH_PRIORITY_CLASS = 0x80,
           IDLE_PRIORITY_CLASS = 0x40,
           NORMAL_PRIORITY_CLASS = 0x20,
           PROCESS_MODE_BACKGROUND_BEGIN = 0x100000,// 'Windows Vista/2008 and higher
           PROCESS_MODE_BACKGROUND_END = 0x200000,//   'Windows Vista/2008 and higher
           REALTIME_PRIORITY_CLASS = 0x100
    }
    
    
    public static bool SetProcessPriority(Process process, PriorityClass priorityClass) =>
      SetPriorityClass(process.Handle, priorityClass);

    Но так делать не нужно, тк есть свойство Process.PriorityClass
    Через него можно так:
    public static void SetProcessPriority(Process process, ProcessPriorityClass priorityClass) =>
      process.PriorityClass = priorityClass;
    Ответ написан
    Комментировать
  • Как привести набор Task с разными возвращаемыми результатами к набору Task с результатами в виде общего интерфейса?

    Можно закостылить примерно так:
    serversStatisticRequests.Add(service.GetBasicStatus(server).ContinueWith(x => (IResponse) x.Result));
    serversStatisticRequests.Add(service.GetFullStatus(server).ContinueWith(x => (IResponse) x.Result));
    Ответ написан
    3 комментария
  • CMake. Как подключить библиотеку из файла?

    @klirichek
    Так у вас либа из двух частей - собственно, архив .a, и хедер (или хедеры).

    install(TARGETS approx_lib LIBRARY DESTINATION lib) - ставит только собранный target (т.е. непосредственно файл статик либы), но не хедер!

    Если не производить установку - можно либу подключить как add_subdirectory с путём к исходникам. Тогда она будет частью основного проекта, будет собираться вместе с ним и всё нужное найдётся (покуда target_include_directories прописан и знает, где искать).

    Если устанавливать - то, очевидно, надо установить и хедеры тоже. И ещё как-то сообщить проекту, где что лежит.

    Вот кусочек из нашей кастомной сборки icu (пусть имя пакета будет foo, а не icu. А namespace - baz. Так интереснее!)
    add_library(icu .....)
    target_include_directories(icu PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/source/common>$<INSTALL_INTERFACE:include/icu>)
    install ( TARGETS icu EXPORT icuExport RUNTIME DESTINATION lib LIBRARY DESTINATION lib  )
    install ( DIRECTORY source/common/unicode DESTINATION include/icu FILES_MATCHING PATTERN "*.h")
    
    # install exports
    set ( CMAKE_CMAKE_DIR "lib/cmake/foo" )
    install ( EXPORT icuExport FILE foo-targets.cmake DESTINATION "${CMAKE_CMAKE_DIR}" NAMESPACE baz:: )
    
    file ( WRITE foo-config.cmake 
    "if(NOT TARGET baz::icu)
        include(\"\${CMAKE_CURRENT_LIST_DIR}/foo-targets.cmake\")
    endif()")
    install ( FILES foo-config.cmake DESTINATION "${CMAKE_CMAKE_DIR}" )


    Здесь несколько моментов.
    Во-первых, обратите внимание на target_include_directories. Там два пути. Один будет работать при сборке, второй - при инсталляции. Т.е. когда собирается либа, либо подключается через add_subdirectory - найдётся нужное по первому пути. После установки - по второму, и этот второй - относительный.

    Во-вторых, при установке задано имя export. Это что-то вроде именованного набора разных свойств, которые cmake накапливает из добавленных с этим именем целей и потом может оформить в файл экспорта. В данном случае туда попадает явно прописанная библиотека, и неявно - include-path от неё, последний потому что он изначально включён как public.

    В-третьих, собственно, ставим помимо таргета и сами хедеры!

    И в-последних, ставим то, что "накопил" экспорт. Первый файл foo-targets.cmake. Второй - который будет работать при поиске пакета (я его осознанно упростил, на самом деле он длиннее) foo-config.cmake.

    Всё это куда-то ставится. Например, в /root/bar (для определённости) - как `cmake --install . --prefix /root/bar`. У вас оно прямо в систему, но тут спецом левый путь, чтобы глазами было видно, как он в конфиге пробрасывается и используется.

    Потом в самом проекте - не надо никаких find_library, всё же известно, где!
    LIST (APPEND CMAKE_PREFIX_PATH "/root/bar")
    find_package(foo)
    
    add_executable(my_prog main.cpp)
    target_link_libraries(my_prog PRIVATE baz::icu)


    Собственно, всё.

    find_package сперва пытается найти модуль FindFoo.cmake. Такого нет. Потом пытается найти конфиг FooConfig.cmake или foo-config.cmake. Он разыскивается по указанному префиксу (там весьма развесистый алгоритм, который умеет заглядывать в разные папки, в доках всё есть) и включается. Он, в свою очередь, включает. foo-targets.cmake, сгенерированный из экспорта. И вот там и находится вся магия.

    ... # это сгенерированный код!
    # Create imported target baz::icu
    add_library(baz::icu STATIC IMPORTED)
    
    set_target_properties(baz::icu PROPERTIES
      INTERFACE_COMPILE_DEFINITIONS "U_STATIC_IMPLEMENTATION;U_CHARSET_IS_UTF8=1;U_NO_DEFAULT_INCLUDE_UTF_HEADERS=1"
      INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include/icu"
    )
    ...
    # Load information for each installed configuration.
    get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
    file(GLOB CONFIG_FILES "${_DIR}/foo-targets-*.cmake")
    foreach(f ${CONFIG_FILES})
      include(${f})
    endforeach()
    ...
    ... а это файл foo-targets-relwithdebinfo.cmake
    # Import target "baz::icu" for configuration "RelWithDebInfo"
    set_property(TARGET baz::icu APPEND PROPERTY IMPORTED_CONFIGURATIONS RELWITHDEBINFO)
    set_target_properties(baz::icu PROPERTIES
      IMPORTED_LINK_INTERFACE_LANGUAGES_RELWITHDEBINFO "CXX"
      IMPORTED_LOCATION_RELWITHDEBINFO "${_IMPORT_PREFIX}/lib/libicu.a"
      )


    а вообще в доках cmake (не надо никаких левых вики/SO!) этой теме посвящён большой и подробный раздел.
    Ответ написан
    Комментировать
  • Как правильно построить структуру проекта используя cmake?

    @klirichek
    либа - это обычно файл (.a, .lib, .so, .dll, .dylib - зависит от статики/динамики) + хедеры, которые должно включить приложение, использующее либу.

    При разработке одновременно либы и приложения add_subdirectory достаточно очевидный вариант, покуда объединяет их оба в один проект. Желательно позаботиться о модульности (раз уж вы поделили проект на две части - значит, это зачем-то было нужно!).

    В папке с либой должен быть свой собственный CMakeLists.txt, собирающий либу; он должен быть самодостаточным для сборки. Т.е. если ей нужны какие-то зависимости - чтобы они искались именно для проекта либы, а не "где-то выше". Т.е какие-то исходники, какие-то find(), потом add_library(name). И нужно определить, что из либы должно увидеть использующее её приложение. Это делается через задание свойств target_XXX(). Например, чтобы показать консумеру путь к нужным хедерам - target_include_directories, чтобы добавить ключи компиляции - target_compile_definitions(). В современном cmake это можно настроить как в настоящем ООП - свойства, нужные для сборки самой либы (например, зависимости, с которыми она статически линкуется. Ей нужны, но как слинковались - консумеру они уже невидимы и ненужны); свойства, нужные консумеру, но не нужные для сборки либы (например, хедеры, специфичные для включения либы, но не нужные для её сборки), и общие свойства, нужные как для либы, так и для её пользователей. Смысл в том, что все эти "настройки для внешних пользователей" не кладутся в некие глобальные переменные cmake (так делали многие годы, но это далеко не best practices), а определяются как свойства самой библиотеки. И вишенкой на торте, в конце проекта либы можно дописать для неё экспорт и алиас (зачем это нужно - чуть ниже).

    export(TARGETS mylib FILE "mylib-targets.cmake" NAMESPACE mylib::)
    add_library(mylib::mylib ALIAS mylib)

    Приложение, использующее либу, должно, во-первых, найти её. И во-вторых, слинковать. Про add_subdirectory - понятно. Добавляете папку и либа доступна. Другой вариант - если либа уже устоялась и НЕ хочется каждый раз её пересобирать. Тогда вместо add_subdirectory включаете (через include) файлик 'mylib-targets.cmake', который будет в сборочной папке либы. На машине разработчика это вполне рабочий вариант! Ну и крайний вариант - это делать полноценный экспорт, тогда пользователи смогут находить либу через штатный find_package().
    После нахождения либа добавляется единственной строчкой:

    target_link_libraries(myprog PUBLIC mylib::mylib)

    Благодаря прописанным свойствам либы эта строчка автоматически добавляет всё необходимое - пути к хедерам, либу для линковки, дополнительные параметры компиляции и т.д. (раньше во время глобальных переменных подразумевалось, что после нахождения либы с помощью find_package у вас появлялось несколько переменных, вида mylib_FOUND - что оно нашлось, mylib_INCLUDE_DIRECTORIES - путь к хедерам, mylib_LIBRARIES - что линковать. А если либа появлялась через add_subdirectory, там вообще фантазия на тему "как сообщить о себе" ничем не ограничивалась, что, в свою очередь, приводило к лапшевидному коду, который использовал библиотеку. Со свойствами целей это всё уже не нужно!). Ну а имя mylib::mylib - оно работает как для импортированной либы (через включение mylib-targets.cmake), так и для add_subdirectory(), именно для этого оно было добавлено там как алиас.

    Итого, в основном проекте у вас будет что-то вроде

    add_subdirectory(mylib)
    target_link_libraries(myprog PUBLIC mylib::mylib)

    или

    include (mylib/build/mylib-targets.cmake)
    target_link_libraries(myprog PUBLIC mylib::mylib)

    или

    find_package(mylib REQUIRED)
    target_link_libraries(myprog PUBLIC mylib::mylib)

    Первый вариант - для одновременной разработки. В IDE будут исходники и основного проекта, и либы сразу. Тёмная сторона - когда сделаете clean all, либа тоже сотрётся :) (что очевидно)
    Второй - для приложения. Либа будет всегда под рукой, но уже как бинарь. Линковаться можно сколько угодно, при очистке ничего не сотрётся, путь привязан к папке (двинуть в другую папку нельзя, потому что в файле прописаны абсолютные пути).
    Третий - для широкой разработки. Когда либа уже отдельно, и ставится отдельно, и кто-то с ней что-то разрабатывает. Это самый цивилизованный вариант, папку можно двигать куда угодно, главное сообщить cmake, где её искать. Но настраивать это чуть сложнее и не всегда оправдано.

    И да - если ещё поизучать cmake, то либа - это не обязательно библиотека для линковки "в общепринятом смысле". Но это просто набор свойств (include-папки, опции компилятора, опции линковки и т.д.), инкапсулированные в нечто под названием "библиотека". Например, можно определить либу для задания варнингов компилятора -wall, где не будет ни исходников, ни библиотек, а только один параметр компилятора. И это вполне нормальный и рабочий способ! Помимо статических либ для чуть-чуть ускорения сборки можно использовать либу типа object. Это просто набор скомпилированных объектников, которые не пакуются в отдельный файл .a или .lib. а прямо так передаются в зависимые проекты. На одну операцию упаковки/распаковки меньше ).
    Ответ написан
    2 комментария
  • На сколько плохо иметь статический список внутри класса, в добавляются новые экземпляры этого класса через конструктор?

    yarosroman
    @yarosroman Куратор тега C#
    C# the best
    А можно поинтересоваться смыслом данной конструкции? Это не рекурсивность, это вполне можно назвать циклической ссылкой, хотя и неявной. Сборщик мусора вполне собирает такие вещи.
    Ответ написан
    2 комментария
  • Как вытащить все значения некоторого поля из json на C#?

    Десериализуешь json, потом делаешь data.Select(x=>x.Name).ToArray()
    // Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse); 
        public class Hotel    {
            public int id { get; set; } 
            public int countryId { get; set; } 
            public string country { get; set; } 
            public string countryUrl { get; set; } 
            public int regionId { get; set; } 
            public string region { get; set; } 
            public string regionUrl { get; set; } 
            public string hotelType { get; set; } 
            public string name { get; set; } 
            public string comment { get; set; } 
            public string imageFolder { get; set; } 
            public string imageHotel { get; set; } 
            public string minPrice { get; set; } 
            public bool showHalfPrice { get; set; } 
            public string minPriceCurrency { get; set; } 
            public List<object> restTypes { get; set; } 
            public bool tour3D { get; set; } 
            public string video { get; set; } 
            public bool tezRecommend { get; set; } 
            public bool tezPriority { get; set; } 
            public bool tezOnly { get; set; } 
            public string price { get; set; } 
        }
    
        public class Root    {
            public Hotel[] hotels { get; set; } 
        }


    var data = JsonConvert.DeserializeObject<Root>(jsonText);
    var names = data.hotels.Select(x=>x.name).ToArray();

    Используйте Newtonsoft.Json или System.Text.Json
    Ответ написан
    1 комментарий
  • Каким образом можно в один exe всунуть музыку вне зависимости от наличия той на пк?

    FutureAnge1
    @FutureAnge1
    Педалирую потихоньку...
    Выбираешь нужный файл в Solution Explorer и устанавливаешь значение "Build Action" в "Resource". Теперь к файлу можно обратиться по относительному пути.
    602ec501d2735629735897.jpeg
    Ответ написан
    Комментировать
  • Каким образом можно в один exe всунуть музыку вне зависимости от наличия той на пк?

    HemulGM
    @HemulGM
    Delphi Developer, сис. админ
    Вопрос простой. Добавить файл в ресурсы и читать его из ресурсов.
    Ответ написан
    1 комментарий
  • Перевод из любой системы счисления в десятичную?

    0xD34F
    @0xD34F
    string value

    long index = value[l];

    То есть, вы ждёте, что '1' ('2', '3', ...) будет неявно преобразовано в 1 (2, 3, ...). Зря. Так не будет. Вы получите код соответствующего символа. Ваше счастье, коды цифровых символов расположены один за другим, в порядке возрастания соответствующих им цифр, так что достаточно вычесть код нуля, чтобы получить нужное число:

    long index = value[l] - '0';
    Ответ написан
    1 комментарий
  • Перевод из любой системы счисления в десятичную?

    @OwDafuq
    Чем вам не угодил стандартный Convert.ToString?
    Пример:
    Console.WriteLine(Convert.ToString(5000, 2)); // -> Вывод: 1001110001000
    Ответ написан
    1 комментарий
  • Асинхронный UDP-клиент на C#. Где происходит получение данных?

    @none7
    Там ниже код
    Task.Run(() =>
                {
                    IPEndPoint ipEndPoint = null;
    
                    while (true)
                    {
                        try
                        {
                            var receivedBytes = _client.Receive(ref ipEndPoint);
                            TaskCompletionSource<byte[]> tcs;
                            if (_tcsDictionary.TryGetValue(ipEndPoint, out tcs)) tcs.SetResult(receivedBytes);
                        }
                        catch (SocketException)
                        {
                            ;//при невозможности соединения продолжаем работать
                        }
    
                    }
                });

    Здесь при помощи tcs.SetResult данные передаются в первый кусок кода.
    Ответ написан
    1 комментарий
  • Как заставить работать CentOS 8 через два сетевых интерфейса?

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

    В общем случае задача "ответить на запрос через тот же интерфейс в обход default route" решается с помощью policy routing. Нужно сделать ещё две разных таблицы маршрутизации с нужными роутами и затем выбирать их через ip rule.

    Что касается тормозов при логине, то это сервер пытается проверить в DNS PTR-запись подключающегося. Соответственно, если на сервере с DNS сделать всё хорошо, то и тормозов не будет.
    Ответ написан
    8 комментариев
  • Можно ли сохранить промежуточный образ в контейнер и использовать его для других проектов?

    @zohan1993
    devops
    для минимизации образа с приложением
    multistage-build

    этап 1
    устанавливаете все необходимые инструменты и зависимости для компиляции приложения
    выполняете компиляцию приложения

    этап 2
    устанавливаете все зависимости необходимые для работы приложения
    копируете готовое приложение в новый образ
    Ответ написан
    1 комментарий