[Модуль] Продукты (app_products)

Разработка дополнительных модулей, подключение различных приложений.

Модератор: immortal

fandaymon
Сообщения: 1554
Зарегистрирован: Сб янв 13, 2018 5:00 pm
Благодарил (а): 39 раз
Поблагодарили: 574 раза

Re: Модуль Продукты

Сообщение fandaymon » Сб фев 17, 2018 2:55 pm

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

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

йогурт марки денон - скрипт смотрит что следующее слово марки и сразу же добавляет к йогурту словосочетание марки денон
Аватара пользователя
lanket
Сообщения: 1168
Зарегистрирован: Вт окт 14, 2014 11:27 pm
Откуда: Санкт-Петербург
Благодарил (а): 260 раз
Поблагодарили: 163 раза

Re: Модуль Продукты

Сообщение lanket » Сб фев 17, 2018 9:10 pm

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

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

йогурт марки денон - скрипт смотрит что следующее слово марки и сразу же добавляет к йогурту словосочетание марки денон
Думал про такое но не доперло что можно ключе слово добавлять 'марки' хорошая идея.
Так вообще модуль будет ах.

Отправлено с моего Redmi Note 4 через Tapatalk
Разработка голосового асистента для Мажордомо по любому ключевому слову.
:arrow: Обсужение
:arrow: gitHub 2й версии терминала
:arrow: GitHub модуля для МД
gitHub сырого модуля 2й версии
:arrow: Connect
Rasberry Pi 2, MDM, MySensors. И говорящий апельсин.
Аватара пользователя
lanket
Сообщения: 1168
Зарегистрирован: Вт окт 14, 2014 11:27 pm
Откуда: Санкт-Петербург
Благодарил (а): 260 раз
Поблагодарили: 163 раза

Re: Модуль Продукты

Сообщение lanket » Вс фев 18, 2018 10:43 pm

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

Сергей принял пуллреквест, прикручу твою функцию, тогда модуль вообще бомба будет.

Вопрос только почему некоторые слова БОЛЬШИМИ БУКВАМИ. а вспомогательные маленькими.
Там нельзя их как то все сделать маленькими?
Или первое слово в словосочетании с большой.
Разработка голосового асистента для Мажордомо по любому ключевому слову.
:arrow: Обсужение
:arrow: gitHub 2й версии терминала
:arrow: GitHub модуля для МД
gitHub сырого модуля 2й версии
:arrow: Connect
Rasberry Pi 2, MDM, MySensors. И говорящий апельсин.
fandaymon
Сообщения: 1554
Зарегистрирован: Сб янв 13, 2018 5:00 pm
Благодарил (а): 39 раз
Поблагодарили: 574 раза

Re: Модуль Продукты

Сообщение fandaymon » Вс фев 18, 2018 10:54 pm

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

Сергей принял пуллреквест, прикручу твою функцию, тогда модуль вообще бомба будет.

Вопрос только почему некоторые слова БОЛЬШИМИ БУКВАМИ. а вспомогательные маленькими.
Там нельзя их как то все сделать маленькими?
Или первое слово в словосочетании с большой.
phpmorphy работает только со словами, написанными большими буквами, поэтому то что возвращает phpmorphy написано большими буквами, а предлог + слово идущее за ним берётся так, как оно было написано в оригинале. Конечно никто не мешает конвертировать всё либо в нижний, либо в верхний регистр с помощью strtoupper

elseif ($partsOfSpeech[$is+1][0]=='ПРЕДЛ') {
$product=$base_forms[$is][0] . ' ' . strtoupper($words[$is+1]) . ' ' . strtoupper($words[$is+2]);
$is=$is+2;
За это сообщение автора fandaymon поблагодарил:
lanket (Вс фев 18, 2018 11:54 pm)
Рейтинг: 1.16%
Аватара пользователя
lanket
Сообщения: 1168
Зарегистрирован: Вт окт 14, 2014 11:27 pm
Откуда: Санкт-Петербург
Благодарил (а): 260 раз
Поблагодарили: 163 раза

Re: Модуль Продукты

Сообщение lanket » Вс фев 18, 2018 11:59 pm

Не стерпел.
Добавил обработку от fandaymon словосочетаний с помошью phpmorhpy .

Работает ;)

Отправил пуллреквест Сергею.
Для нетерпиливых ссылка на мой репозитарий

Там вынес функцию в отдельный файл. Поэтому в отличии от оригинала добавился один файл и в основном файле осталось обявление функции и инклюд.
За это сообщение автора lanket поблагодарил:
fandaymon (Пн фев 19, 2018 7:14 pm)
Рейтинг: 1.16%
Разработка голосового асистента для Мажордомо по любому ключевому слову.
:arrow: Обсужение
:arrow: gitHub 2й версии терминала
:arrow: GitHub модуля для МД
gitHub сырого модуля 2й версии
:arrow: Connect
Rasberry Pi 2, MDM, MySensors. И говорящий апельсин.
fandaymon
Сообщения: 1554
Зарегистрирован: Сб янв 13, 2018 5:00 pm
Благодарил (а): 39 раз
Поблагодарили: 574 раза

Re: Модуль Продукты

Сообщение fandaymon » Пн фев 19, 2018 7:20 pm

Пробую ввод голосом, вылезает ошибка - нету поля Category_ID в таблице product_categories - там только ID

SELECT * FROM product_categories WHERE 1 AND TITLE LIKE '%ХЛЕБ%' ORDER BY CATEGORY_ID, TITLE

Видимо там таблица должна быть не product_categories, а просто products
Аватара пользователя
lanket
Сообщения: 1168
Зарегистрирован: Вт окт 14, 2014 11:27 pm
Откуда: Санкт-Петербург
Благодарил (а): 260 раз
Поблагодарили: 163 раза

Re: Модуль Продукты

Сообщение lanket » Пн фев 19, 2018 8:47 pm

fandaymon писал(а):Пробую ввод голосом, вылезает ошибка - нету поля Category_ID в таблице product_categories - там только ID

SELECT * FROM product_categories WHERE 1 AND TITLE LIKE '%ХЛЕБ%' ORDER BY CATEGORY_ID, TITLE

Видимо там таблица должна быть не product_categories, а просто products
Посмотрю чуть позже, вроде работало.

Отправлено с моего Redmi Note 4 через Tapatalk
Разработка голосового асистента для Мажордомо по любому ключевому слову.
:arrow: Обсужение
:arrow: gitHub 2й версии терминала
:arrow: GitHub модуля для МД
gitHub сырого модуля 2й версии
:arrow: Connect
Rasberry Pi 2, MDM, MySensors. И говорящий апельсин.
fandaymon
Сообщения: 1554
Зарегистрирован: Сб янв 13, 2018 5:00 pm
Благодарил (а): 39 раз
Поблагодарили: 574 раза

Re: Модуль Продукты

Сообщение fandaymon » Пн фев 19, 2018 10:00 pm

Как-то очень замороченно поиск сделан - из-за этого и проблемы. В функции product_categories_search используются переменные $title и $sortby, но поскольку в функции product_AddtoListfromVoice они не определяются как глобальные, то фильтр и сортировка берутся те, которые заданы в product_search. Если перед поиском категорий написать
global $sortby;
global $title;
то вроде бы всё отрабатывает. Но честно говоря выполнить SQLSelect было бы гораздо проще 8-)

И ещё вылезла проблема - когда даёшь команду воду, то добавляется вод, а не вода. Кроме как захардкодить слово вода ничего пока в голову не приходит.
fandaymon
Сообщения: 1554
Зарегистрирован: Сб янв 13, 2018 5:00 pm
Благодарил (а): 39 раз
Поблагодарили: 574 раза

Re: Модуль Продукты

Сообщение fandaymon » Вт фев 20, 2018 1:29 am

Переделал файл product_addToListFromVoice.php так
СпойлерПоказать

Код: Выделить всё

<?php

//$command='череный молотый перец белого лука гель для душа';
require_once(ROOT . "lib/phpmorphy/common.php");
$opts = array(
 'storage' => PHPMORPHY_STORAGE_MEM,
 'predict_by_suffix' => true,
 'predict_by_db' => true,
 'graminfo_as_text' => true,
 );
$dir = ROOT . 'lib/phpmorphy/dicts';
$lang = 'ru_RU';
        try {
            $morphy = new phpMorphy($dir, $lang, $opts);
            $this->morphy =& $morphy;
        } catch (phpMorphy_Exception $e) {
            die('Error occured while creating phpMorphy instance: ' . PHP_EOL . $e);
        }
        $words = explode(' ', $command);
        $base_forms = array();
        $partsOfSpeech=array();
        $f_word=array();
        $totals = count($words);
        for ($is = 0; $is < $totals; $is++) {
            if (preg_match('/^(\d+)$/', $words[$is])) {
                $base_forms[$is] = array($words[$is]);
            } else {
                $Word = mb_strtoupper($words[$is], 'UTF-8');
                $base_forms[$is] = $morphy->getBaseForm($Word);
                $partsOfSpeech[$is] = $morphy->getPartOfSpeech($Word);
                $f_word[$is] = $morphy->getGramInfo($Word);
                $base_forms[$is][]=$words[$is];
            } 
        }


for ($is = 0; $is < $totals; $is++) {
    if ($base_forms[$is][0]=='ВОД') $base_forms[$is][0]='ВОДА';
    if ($partsOfSpeech[$is][0]=='С') {
    
        if (($is+1)<$totals) {
            if ($partsOfSpeech[$is+1][0]=='С') {
        if ($base_forms[$is+1][0]=='МАРКА') {
            $product=$base_forms[$is][0]. ' ' . $words[$is+1] . ' ' . $words[$is+2];
            $is=$is+2;
        }
        else {
            $product=$base_forms[$is][0];
        }
            }
            elseif ($partsOfSpeech[$is+1][0]=='ПРЕДЛ') {
                $product=$base_forms[$is][0] . ' ' . $words[$is+1] . ' ' . $words[$is+2];
                $is=$is+2;
            }
             elseif ($partsOfSpeech[$is+1][0]=='П') {
                $product=$base_forms[$is][0] ;

            }

        }
        else {
            $product=$base_forms[$is][0];
        }
    }
    elseif ($partsOfSpeech[$is][0]=='П') {
        if (($is+1)<$totals) {
            if ($partsOfSpeech[$is+1][0]=='С') {

                if (count($base_forms[$is+1])>2){
                 // выбираем форму согласованную по роду
                 for ($k= 0; $k < count($f_word[$is][0][0]['grammems']); $k++) {
                  $gram=$f_word[$is][0][0]['grammems'][$k];
                  if ($gram=='МР' or $gram=='СР' or $gram=='ЖР') {
                   break;
                  }
                 }
                 $kkk=0;
                 for ($kk= 0; $kk < count($base_forms[$is+1])-1; $kk++) {

                  for ($k= 0; $k < count($f_word[$is+1][$kk][0]['grammems']); $k++) {
                    if ($gram==$f_word[$is+1][$kk][0]['grammems'][$k]) {
                     $kkk=1;
                     break;
                    }
                  }
                  if ($kkk==1) break;
                 }
                $product=$base_forms[$is][0] .' ' . $base_forms[$is+1][$kk] ;
                $is=$is+1; 
                 
                }
                 else {
                $product=$base_forms[$is][0] .' ' . $base_forms[$is+1][0] ;
                $is=$is+1; 
                } 
            }
            elseif ($partsOfSpeech[$is+1][0]=='П') {
                if (($is+2)<$totals) {
                    if ($partsOfSpeech[$is+2][0]=='С') {

                        if (count($base_forms[$is+2])>2){
                            // выбираем форму согласованную по роду
                            for ($k= 0; $k < count($f_word[$is][0][0]['grammems']); $k++) {
                                $gram=$f_word[$is][0][0]['grammems'][$k];
                                if ($gram=='МР' or $gram=='СР' or $gram=='ЖР') break;
                   
                            }
                 
                            $kkk=0;
                            for ($kk= 0; $kk < count($base_forms[$is+2])-1; $kk++) {

                                for ($k= 0; $k < count($f_word[$is+2][$kk][0]['grammems']); $k++) {
                                    if ($gram==$f_word[$is+2][$kk][0]['grammems'][$k]) {
                                        $kkk=1;
                                        break;
                                    }
                                }
                                if ($kkk==1) break;
                            }
                            $product=$base_forms[$is][0] .' ' . $base_forms[$is+1][0] . ' ' . $base_forms[$is+2][$kk] ;
                            $is=$is+2; 
                 
                        }
                        else {
                            $product=$base_forms[$is][0] .' ' . $base_forms[$is+1][0] .' ' . $base_forms[$is+2][0];
                            $is=$is+2; 
                        }
                    }
                    else {
                        $product=$base_forms[$is][0] .' ' . $base_forms[$is+1][0];
                        $is=$is+1;
                    }    
                }
                else {
                    $product=$base_forms[$is][0] .' ' . $base_forms[$is+1][0];
                    $is=$is+1;
                }    
            }                
        }
        else {
            $product=$base_forms[$is][0];
        }    
    }        

    $product = strtolower($product);
     
    if($debugEnabled) debmes('Products produkt:'. $product);
                
    $id=Get_Product_ID( $product);
    if ($id > 0){
        $this->addToList($id);
        if($debugEnabled) debmes('Products produkt '.$product.' found, ID:'. $id);
    }
    Else {
        if($debugEnabled) debmes('Products produkt '.$product.' not found, adding');
        $category_id = Get_Category_ID("Неотсортированные");
        if ($category_id > 0){
            if($debugEnabled) debmes('Products category exiting unknown');
            $this->category_id = $category_id;
        } 
        Else {
            if($debugEnabled) debmes('Products creating unknown');
               $Record = Array();
               $Record['TITLE'] = "Неотсортированные";
               $Record['ID']=SQLInsert('product_categories', $Record);
            $category_id = $Record['ID'];
                            
            if($debugEnabled) debmes('Products produkt '.$product.' adding to created unknown');
        }

           $Record = Array();
           $Record['TITLE'] = $product;
          $Record['CATEGORY_ID'] = $category_id;
          $Record['QTY'] = 1;

           $Record['ID']=SQLInsert('products', $Record);
        $id = $Record['ID'];

        $this->addToList($id);
        if($debugEnabled) debmes('Products produkt '.$product.' not found, added to category id '.$category_id);
    }


} 

function Get_Product_ID($product) {
$res=SQLSelectOne("select ID from products where TITLE='" . $product . "'");

$id=0;
if ($res['ID']) {
 $id=$res['ID'];
}  

return $id;
}

function Get_Category_ID($category) {
$res=SQLSelectOne("select ID from product_categories where TITLE='" . $category . "'");
$id=0;
if ($res['ID']) {
 $id=$res['ID'];
}
return $id;

}

?>
Вынес поиск продуктов и категории в этот же самый файл. Добавил проверку на конструкцию йогурт марки денон. И захардкорил ВОДУ. Внезапно вылез неприятный глюк - модуль определяет слово КРАСНЫЙ и как существительное и как прилагательное. Видимо надо добавлять проверку - не является ли существительное ещё и прилагательным.

Попробую добавить ещё отслеживание конструкций хлеб белый и отслеживание количества...
За это сообщение автора fandaymon поблагодарил:
lanket (Вт фев 20, 2018 9:14 am)
Рейтинг: 1.16%
Аватара пользователя
lanket
Сообщения: 1168
Зарегистрирован: Вт окт 14, 2014 11:27 pm
Откуда: Санкт-Петербург
Благодарил (а): 260 раз
Поблагодарили: 163 раза

Re: Модуль Продукты

Сообщение lanket » Вт фев 20, 2018 10:31 am

fandaymon писал(а):Переделал файл product_addToListFromVoice.php ...
Вчера так и не успел добраться до компа.
Отправил пулл реквест Сергею с твоими доработками.

У тебя опыта побольше в программировании, может тебе проще будет напрямую пуллреквесты сергею слать?

А то я как то лишнее звено получаюсь. Рад что идея прижилась. Спасибо тебе за доработки.

Вот его репозитарий модуля продукты

Но если по какой либо причине неудобно, могу и я отправлять изменения.
Разработка голосового асистента для Мажордомо по любому ключевому слову.
:arrow: Обсужение
:arrow: gitHub 2й версии терминала
:arrow: GitHub модуля для МД
gitHub сырого модуля 2й версии
:arrow: Connect
Rasberry Pi 2, MDM, MySensors. И говорящий апельсин.
Ответить