<?php // Полная загрузка сервисных книжек, создан 2025-01-05 12:44:55
global $wpdb2;
global $failure;
global $file_hist;
///// echo '<H2><b>Старт загрузки</b></H2><br>';
$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
///// echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}
$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
///// echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}
/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
///// echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
///// echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist); ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7]; ////получаем размер файла
$m_mtime_file=$masiv_data_file[9]; ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file
///// echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
///// echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
///// echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);
if ($results)
{ foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));
////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
///// echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
///// echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}
////загружаем данные
$table='vin_history'; // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация // (путь от корня web-сервера)
$delim=';'; // Разделитель полей в CSV файле
$enclosed='"'; // Кавычки для содержимого полей
$escaped='\
Вот эту энергию и в мирное русло бы!
(1)Не понял… что не так?
шпарит тупым перебором? или более интеллектуальные варианты решения задачи рбкзака применяются?
(3)Скачай и посмотри, пожалуйста, если интересно. Работает быстро. Из нескольких сотен случайных чисел подбирает сумму в среднем за 5сек. Надо только умело и творчески подойти к процессу. Не веришь — проверь. Генератор случайных чисел включен… Тупой перебор не выложил бы здесь — даже не стал бы позориться. 😉 А энергию свою я употребил, когда потребовалось, на решение 3 разных задач. И в основе их — этот подбор сумм.
(3)О, пардон… это не ты пытался мою энергию в мирное русло направить… 🙂
(4)Лично я не против многообразия. Свои алгоритмы я программировал без шпаргалок. Что получилось — выложил. Мож кому понравятся. Денег не прошу. 🙂 Я не перебираю все.
(7)
1 стартмани стоит каких-никаких денег. Было бы интересно знать суть алгоритма. Фактически все условно быстрые алгоритмы не дают 100% точности кроме рюкзака. А рюкзак требует памяти (на каждую копейку до искомой суммы * количество сумм).
(8)Стартмани стоят для нас с тобой только некоторых усилий… что-то разработал, выложил, получил… Или не так? Была бы моя воля, я бы и даром выложил эту обработку, — не жалко.
Что же до алгоритмов: большая часть суммы подбирается случайно (процент регулируешь ползунком), а потом — да, тупой перебор, но отбрасываются все тупиковые варианты. И если процесс длится долго, например, больше 20секунд, случайный набор чисел меняется на новый, если указано несколько попыток подбора.
(3)Кстати, обращаю твое внимание на картинку к статье. Внизу строчка: требуемая сумма подобрана с первой попытки. На попытку не больше 20сек. было отведено. (Обычно, я и 20секунд не выставлял, а 5-10). Чисел для перебора около 140. Как ты знаешь, простой перебор за такое время результат не даст. На случайном наборе чисел все работает изумительно. Медленнее всего подбираются слишком маленькие и слишком большие (приграничные) суммы.
интересует за сколько отработает алгоритм для ~100 разных подборов, на которых в каждом подборе ~15 чисел и они близки друг к другу
(11)Полагаю, надо провести следственный эксперимент… давай набор чисел и требуемую сумму. Посмотрю.
так мне без разницы — что числа выдавать что смотреть… сам посмотрю если припрет.
а если припрет — придетяс из разработки выдирать колд, или там унутре есть функция на вход клоторой масив с данными — на выходе результат?
(13)Вызываешь обработку модально, передав в нее список значений. Получив результат, давишь кнопку «Готово», — вываливаешься из обработки. На выходе в списке значений имеем требуемое. Задачи подобного рода я не решаю на полном автомате, — в меру своих умений вмешиваюсь в процесс получения результата. И обычно его получаю быстро, даже когда требуется полное совпадение с суммой.
Передается именно список значений, а не массив. Это позволяет решать задачи количественно-суммовые. Например, из остатков подобрать номенклатуру на заданную сумму в количестве и ценах.
В принципе, возможно все запускать на автомате, когда требуется сделать большое количество подборов. На вход подаешь не только массив чисел, но и указываешь длительность попытки подбора с неограниченным количеством попыток. Вот только я пока что не предусмотрел на этот случай выход из обработки по завершении подбора. Но это пустячное изменение алгоритмов.
Ану подскажите, есть ТЧ дока, мне нужно из этой ТЧ выбрать коство шт. товару на определенную сумму, и я знаю, что эта сумма есть в этой тч, эта обработка такое решает?
(15)И «да», и «нет». «Нет», — потому что эта обработка позволяет только сумму подобрать из имеющихся значений. Но также и «Да», потому что она лежит в основе решения твоей задачи. Вот только прежде чем перейти к подбору суммы по номенклатуре, необходимо до вызова обработки специальным образом обработать эту самую номенклатуру. Такой простой пример: есть у тебя 6 карандашей на сумму 24 рубля. В обработку передаешь несколько элементов по этим карандашам в списке значений:
12 — Карандаш 3шт.
8 — Карандаш 2шт.
4 — карандаш 1шт.
Эти 3 элемента позволяют набрать суммы; 4, 8, 12, 16, 20, 24
Допустим тебе нужна сумма 20. Эта обработка в списке значений вернет тебе 2 записи:
12 — Карандаш 3шт.
8 — Карандаш 2шт.
Обработав их, получишь: 5 карандашей на сумму 20.
отлично работает, когда необходимо подделать что-то в оборотке)))
(17) Очень рад, что она тебе помогла нести светлое людям. 🙂
Каким то образом можно ограничить выбор только определенным количеством элементов, т.е. чтобы сумма получалась как сумма только 5 (или любого другого числа) элементов из всего набора чисел?
(19) Здравствуйте. Этой обработкой можно получить разные комбинации чисел на определенную заданием сумму. Можно, разве что, смотреть на то, что получилось по количеству чисел и выбирать подходящую комбинацию (программно, разумеется. Это не требует изменений обработки).
Или, найдите в коде то место, где анализируется промежуточный результат поиска и включите отказ от любого из них, которое не удовлетворяет Вашему дополнительному условию (уже много чисел!),- это может немного ускорить подбор. И это еще не все ускорение, которое можно получить… есть варианты. Но, на текущий момент такая функциональность не была предусмотрена.
(20)
Подскажите пожалуйста, где это происходит в коде.
Могу я поинтересоваться, какую задачу Вы решаете? Для чего такое ограничение? Оно может весьма существенно увеличить время подбора…
(21) Очевидно, что нужно ввести реквизит формы на количество слагаемых результата.
Функция ВыбратьСочетания (ИзЭн, ПоЭм) — запускает последовательность сочетаний ИзЭн ПоЭм; не трогаем.
Функция ПолучитьСочетание (Сочетание, ИзЭн, ПоЭм) — формирует следующее сочетание ИзЭн ПоЭм; не трогаем.
Изменения нужно внести в Процедура ОбработатьСочетание (Сочетание)
Сочетание — массив, количество элементов которого и есть количество слагаемых, которое нужно держать на контроле. Обращаю внимание, что в этой процедуре нарушается «нормальная» последовательность сочетаний, отсекаются заведомо не приводящие к нужному результату.
И это еще не все.
Процедура СлучайныйПодбор() — надо либо отказываться от случайного подбора, когда есть ограничение на к-во слагаемых, либо в него тоже внести поправки с учетом новых требований. И над этим нужно по-медитировать…
(21) Меня только что осенило… надо ведь попросту рассмотреть только сочетания ИзЭн ПоЭм, когда ПоЭм равно требуемому количеству слагаемых за вычетом количества случайно подобранных. И тогда Процедура ОбработатьСочетание (Сочетание) — не трогаем. Все просто.
Понятное дело, в случайном подборе не может быть к-во слагаемых большее либо равное требуемому. Оно должно быть меньше, чтобы было еще что сочетать из оставшихся чисел.
Сохранение количества и суммы при изменении цены.
Это совсем другого порядка задача. Предложенное мной выше решение — это совсем-совсем не то, что требуется. Я то полагал, что нужно подобрать сумму при фиксированном количестве слагаемых. В принципе, и это решение подойдет, если целочисленное количество и всю номенклатуру отдельными позициями подать в подбор, когда к-во равно 1. Да, так сработает.
Что такое и планировал сделать развернуть все позиции до 1, и дальше составлять комбинацию.
Показать
(25)
(27) Еще раз… в подбор забрасываем всю номенклатуру: каждая строка подбора это отдельная (кво=1) позиция номенклатуры. Например, у нас 10 наименований по 5 штук каждого — итого 50 строк подбора (сумма каждой строки — это цена товара).
Модифицируем алгоритм. Сейчас рассматриваются все сочетания строк подбора:1 из 50; 2 из 50; 3 из 50; … ; 49 из 50; 50 из 50. Цикл в цикле:
Сочетание = ВыбратьСочетания (ИзЭн, ПоЭм) ;
И в цикле: ПолучитьСочетание (Сочетание, ИзЭн, ПоЭм);
ОбработатьСочетание (Сочетание)
Например, нужно подобрать 13 позиций номенклатуры из 50 на некую заданную сумму. Что мы делаем?
1. случайно подбираем сколько-то. Например, 8.
2. Оставшиеся 5 получаем путем сочетаний из 42(ИзЭн) по 5(ИзЭм). Почему из 42, а не из 50? Да потому что 8 мы подобрали уже случайно. (Случайный подбор не нужно менять, — он регулируется на форме ползунком.)
В-общем, все самое сложное я уже сделал, а Вам осталось модифицировать несколько строк программного кода. Желаю удачи. 🙂
Как скачать????