Бір жобаның тарихы немесе мен Asterisk және Php негізіндегі АТС құруға 7 жыл жұмсадым

Мен сияқты сіздердің көпшілігіңізде ерекше нәрсе жасау идеясы болғаны сөзсіз. Бұл мақалада мен АТС әзірлеу кезінде кездесетін техникалық мәселелер мен шешімдерді сипаттайтын боламын. Бәлкім, бұл біреуге өз идеясын шешуге, ал біреуге жақсы өткен жолмен жүруге көмектесетін шығар, өйткені мен де пионерлердің тәжірибесін пайдаландым.

Бір жобаның тарихы немесе мен Asterisk және Php негізіндегі АТС құруға 7 жыл жұмсадым

Идея және негізгі талаптар

Және бәрі тек махаббаттан басталды Жұлдыздар (коммуникациялық қосымшаларды салу үшін негіз), телефония мен қондырғыларды автоматтандыру freepbx (веб-интерфейс үшін Жұлдыздар). Егер компанияның қажеттіліктері нақты болмаса және мүмкіндіктерге сәйкес келсе freepbx - бәрі тамаша. Бүкіл орнату XNUMX сағат ішінде өтті, компания конфигурацияланған АТС, ыңғайлы интерфейс және қысқа дайындық пен қажет болса қолдау алды.

Бірақ ең қызықты тапсырмалар стандартты емес болды, содан кейін ол соншалықты керемет емес еді. Жұлдыздар көп нәрсені жасай алады, бірақ веб-интерфейсті жұмыс тәртібінде ұстау үшін бірнеше есе көп уақыт жұмсау қажет болды. Осылайша, шағын деталь АТС-тің қалған бөлігін орнатудан әлдеқайда көп уақыт алуы мүмкін. Мәселе веб-интерфейсті жазу үшін көп уақытты қажет ететінінде емес, мәселе архитектуралық ерекшеліктерде. freepbx. Архитектуралық тәсілдер мен әдістер freepbx php4 уақытында құрастырылған және сол сәтте барлығын қарапайым және ыңғайлы етуге болатын php5.6 болды.

Соңғысы диаграмма түріндегі графикалық диалпландар болды. Мен осындай нәрсені салуға тырысқанда freepbx, Мен оны айтарлықтай қайта жазуым керек екенін және жаңа нәрсені құру оңайырақ болатынын түсіндім.

Негізгі талаптар мыналар болды:

  • қарапайым орнату, тіпті жаңадан бастаған әкімшіге де интуитивті түрде қол жетімді. Осылайша, компаниялар біздің тарапымыздан АТС жөндеуді қажет етпейді,
  • тапсырмаларды тиісті уақытта шешу үшін оңай өзгерту,
  • АТС-пен интеграцияның қарапайымдылығы. У freepbx параметрлерді өзгертуге арналған API болған жоқ, яғни. Сіз, мысалы, үшінші тарап қолданбасынан топтар немесе дауыс мәзірлерін жасай алмайсыз, тек API өзі Жұлдыздар,
  • opensource - бағдарламашылар үшін бұл клиент үшін өзгертулер үшін өте маңызды.

Тезірек даму идеясы барлық функционалдылық нысандар түріндегі модульдерден тұруы болды. Барлық нысандардың жалпы ата-аналық класы болуы керек еді, бұл барлық негізгі функциялардың атаулары бұрыннан белгілі, сондықтан әдепкі іске асырулар бар. Нысандар жол пернелері бар ассоциативті массивтер түріндегі аргументтер санын күрт азайтуға мүмкіндік береді, оны мына жерден табуға болады. freepbx Бүкіл функцияны және кірістірілген функцияларды тексеру арқылы мүмкін болды. Нысандар жағдайында банальды автотолтыру барлық қасиеттерді көрсетеді және тұтастай алғанда өмірді бірнеше есе жеңілдетеді. Сонымен қатар, мұра және қайта анықтау модификациялармен көптеген мәселелерді шешеді.

Қайта өңдеу уақытын бәсеңдететін және болдырмауға тұрарлық келесі нәрсе қайталау болды. Егер қызметкерді теруге жауапты модуль болса, онда қызметкерге қоңырау жіберу қажет барлық басқа модульдер оны пайдалануы керек және өздерінің көшірмелерін жасамауы керек. Сонымен, егер сізге бір нәрсені өзгерту қажет болса, онда сізге тек бір жерде өзгертуге тура келеді және «ол қалай жұмыс істейді» іздеу бүкіл жоба бойынша ізделмей, бір жерде жүргізілуі керек.

Бірінші нұсқа және бірінші қателер

Бірінші прототип бір жылдың ішінде дайын болды. Бүкіл АТС, жоспарланғандай, модульдік болды және модульдер қоңырауларды өңдеу үшін жаңа функцияларды қосып қана қоймай, сонымен қатар веб-интерфейстің өзін өзгерте алады.

Бір жобаның тарихы немесе мен Asterisk және Php негізіндегі АТС құруға 7 жыл жұмсадым
Иә, мұндай схема түріндегі диалплан құру идеясы менікі емес, бірақ бұл өте ыңғайлы және мен де солай істедім. Жұлдыздар.

Бір жобаның тарихы немесе мен Asterisk және Php негізіндегі АТС құруға 7 жыл жұмсадым

Модуль жазу арқылы бағдарламашылар қазірдің өзінде:

  • диаграммада, сондай-ақ сол жақтағы элементтер мәзірінде орналастыруға болатын қоңырауларды өңдеуге арналған жеке функционалдылықты жасаңыз,
  • веб-интерфейс үшін өз беттеріңізді жасаңыз және шаблондарыңызды бар беттерге қосыңыз (егер бет әзірлеушісі мұны қамтамасыз еткен болса),
  • параметрлерді негізгі параметрлер қойындысына қосыңыз немесе жеке параметрлер қойындысын жасаңыз,
  • бағдарламашы бар модульден мұра ала алады, функцияның бір бөлігін өзгерте алады және оны жаңа атпен тіркей алады немесе бастапқы модульді ауыстыра алады.

Мысалы, өзіңіздің дауыстық мәзіріңізді осылай жасауға болады:

......
class CPBX_MYIVR extends CPBX_IVR
{
 function __construct()
 {
 parent::__construct();
 $this->_module = "myivr";
 }
}
.....
$myIvrModule = new CPBX_MYIVR();
CPBXEngine::getInstance()->registerModule($myIvrModule,__DIR__); //Зарегистрировать новый модуль
CPBXEngine::getInstance()->registerModuleExtension($myIvrModule,'ivr',__DIR__); //Подменить существующий модуль

Алғашқы күрделі іске асырулар бірінші мақтаныш пен алғашқы көңілсіздіктерді әкелді. Мен оның жұмыс істегеніне, негізгі мүмкіндіктерді жаңғырта алғаныма қуаныштымын freepbx. Схема идеясының адамдарға ұнағанына қуаныштымын. Әзірлеуді жеңілдетудің көптеген нұсқалары болды, бірақ сол кезде де кейбір тапсырмалар жеңілдетілді.

PBX конфигурациясын өзгертуге арналған API көңілді қалдырды - нәтиже біз қалағандай болмады. Мен бұрынғыдай принципті ұстандым freepbx, Қолдану түймесін басу арқылы бүкіл конфигурация қайта жасалады және модульдер қайта іске қосылады.

Мынадай көрінеді:

Бір жобаның тарихы немесе мен Asterisk және Php негізіндегі АТС құруға 7 жыл жұмсадым
*Теру жоспары - бұл қоңырау өңделетін ереже (алгоритм).

Бірақ бұл опциямен PBX параметрлерін өзгерту үшін қалыпты API жазу мүмкін емес. Біріншіден, өзгертулерді қолдану операциясы Жұлдыздар тым ұзақ және ресурстарды қажет етеді.
Екіншіден, сіз бір уақытта екі функцияны шақыра алмайсыз, өйткені екеуі де конфигурацияны жасайды.
Үшіншіден, ол барлық параметрлерді, соның ішінде әкімші жасаған параметрлерді қолданады.

Бұл нұсқада, сияқты Аскозия, тек өзгертілген модульдердің конфигурациясын генерациялау және тек қажетті модульдерді қайта іске қосу мүмкін болды, бірақ бұл барлық жарты өлшемдер. Тәсілді өзгерту керек болды.

Екінші нұсқа. Мұрын шығарылған құйрық кептеліп қалды

Мәселені шешу идеясы конфигурацияны және теру жоспарын қайта жасау емес еді Жұлдыздар, бірақ ақпаратты дерекқорға сақтаңыз және қоңырауды өңдеу кезінде дерекқордан тікелей оқыңыз. Жұлдыздар Мен дерекқордан конфигурацияларды қалай оқу керектігін бұрыннан білетінмін, жай ғана дерекқордағы мәнді өзгертіңіз және келесі қоңырау өзгерістерді ескере отырып өңделеді, және функция теру жоспарының параметрлерін оқу үшін тамаша болды. REALTIME_HASH.

Ақырында, қайта іске қосудың қажеті жоқ еді Жұлдыздар параметрлерді өзгерткен кезде және барлық параметрлер дереу қолданыла бастады Жұлдыздар.

Бір жобаның тарихы немесе мен Asterisk және Php негізіндегі АТС құруға 7 жыл жұмсадым

Теру жоспарындағы жалғыз өзгерістер кеңейтім нөмірлерін қосу болып табылады кеңестер. Бірақ бұл кішігірім нүктелік өзгерістер болды

exten=>101,1,GoSub(‘sub-callusers’,s,1(1)); - точечное изменение, добавляется/изменяется через ami

; sub-callusers – универсальная функция генерится при установке модуля.
[sub-callusers]
exten =>s,1,Noop()
exten =>s,n,Set(LOCAL(TOUSERID)=${ARG1})
exten =>s,n,ClearHash(TOUSERPARAM)
exten =>s,n,Set(HASH(TOUSERPARAM)=${REALTIME_HASH(rl_users,id,${LOCAL(TOUSERID)})})
exten =>s,n,GotoIf($["${HASH(TOUSERPARAM,id)}"=""]?return)
...

көмегімен теру жоспарына жолды оңай қосуға немесе өзгертуге болады Ами (басқару интерфейсі Жұлдыздар) және бүкіл теру жоспарын қайта жүктеу қажет емес.

Бұл API конфигурациясына қатысты мәселені шешті. Сіз тіпті дерекқорға тікелей кіріп, жаңа топ қосуға немесе өзгертуге болады, мысалы, топ үшін «теру уақыты» өрісіндегі теру уақытын және келесі қоңырау көрсетілген уақытқа созылады (Бұл ұсыныс емес әрекет, себебі кейбір API операциялары қажет Ами қоңыраулар).

Алғашқы қиын іске асырулар қайтадан бірінші мақтаныш пен көңілсіздікті әкелді. Мен оның жұмыс істегеніне қуаныштымын. Деректер базасы маңызды сілтеме болды, дискіге тәуелділік артты, тәуекелдер көп болды, бірақ бәрі тұрақты және проблемаларсыз жұмыс істеді. Ең бастысы, енді веб-интерфейс арқылы жасауға болатын барлық нәрсені API арқылы жасауға болады және сол әдістер қолданылды. Сонымен қатар, веб-интерфейс әкімшілер жиі ұмытып кететін «ПБХ-ға параметрлерді қолдану» түймесінен құтылды.

Көңіл қалдырған жері дамудың күрделене түсуі болды. Бірінші нұсқадан бастап РНР тілі тілде теру жоспарын жасады Жұлдыздар және ол мүлдем оқылмайтын болып көрінеді, сонымен қатар тілдің өзі Жұлдыздар диалплан жазу үшін бұл өте қарапайым.

Бұл қалай көрінді:

$usersInitSection = $dialplan->createExtSection('usersinit-sub','s');
$usersInitSection
 ->add('',new Dialplanext_gotoif('$["${G_USERINIT}"="1"]','exit'))
 ->add('',new Dialplanext_set('G_USERINIT','1'))
 ->add('',new Dialplanext_gosub('1','s','sub-AddOnAnswerSub','usersconnected-sub'))
 ->add('',new Dialplanext_gosub('1','s','sub-AddOnPredoDialSub','usersinitondial-sub'))
 ->add('',new Dialplanext_set('LOCAL(TECH)','${CUT(CHANNEL(name),/,1)}'))
 ->add('',new Dialplanext_gotoif('$["${LOCAL(TECH)}"="SIP"]','sipdev'))
 ->add('',new Dialplanext_gotoif('$["${LOCAL(TECH)}"="PJSIP"]','pjsipdev'))

Екінші нұсқада теру жоспары әмбебап болды, ол параметрлерге байланысты өңдеудің барлық мүмкін нұсқаларын қамтыды және оның өлшемі айтарлықтай өсті. Осының бәрі әзірлеу уақытын едәуір баяулатты және диалпланға тағы да араласу керек деген ойдың өзі мені қынжылтты.

Үшінші нұсқа

Мәселені шешу идеясы генерациялау емес еді Жұлдыздар php жүйесінен теру және пайдалану FastAGI және барлық өңдеу ережелерін PHP-де жазыңыз. FastAGI ол мүмкіндік береді Жұлдыздар, қоңырауды өңдеу үшін розеткаға қосыңыз. Сол жерден пәрмендерді қабылдап, нәтижелерді жіберіңіз. Осылайша, диалпланның логикасы қазірдің өзінде шекарадан тыс Жұлдыздар және кез келген тілде жазылуы мүмкін, менің жағдайда PHP тілінде.

Сынақ пен қателік көп болды. Негізгі мәселе менде көптеген сыныптар/файлдар болды. Нысандарды жасауға, оларды инициализациялауға және бір-бірін бір-бірімен тіркеуге шамамен 1,5 секунд қажет болды және бір қоңыраудағы бұл кешігуді елемеу мүмкін емес.

Инициализация тек бір рет болуы керек еді, сондықтан шешімді іздеу PHP көмегімен қызметті жазудан басталды Тақырыптар. Бір апталық тәжірибеден кейін бұл кеңейтім қалай жұмыс істейтінінің күрделілігіне байланысты бұл опция тоқтатылды. Бір айлық тестілеуден кейін мен PHP-де асинхронды бағдарламалаудан бас тартуға тура келді; маған кез келген PHP бастаушыға таныс қарапайым нәрсе керек болды және PHP үшін көптеген кеңейтімдер синхронды болып табылады.

Шешім құрастырылған C тіліндегі өзіміздің көп ағынды қызметіміз болды PHPLIB. Ол барлық ATS PHP файлдарын жүктейді, барлық модульдердің инициализациясын күтеді, бір-біріне кері қоңырауды қосады және бәрі дайын болғанда, оны кэштейді. Сұрау кезінде FastAGI ағын құрылады, онда барлық сыныптар мен деректердің кэшінен көшірме шығарылады және сұрау php функциясына жіберіледі.

Бұл шешім арқылы біздің қызметімізге қоңырауды жіберуден бірінші пәрменге дейінгі уақыт Жұлдыздар 1,5 секундтан 0,05 секундқа дейін төмендеді және бұл уақыт жобаның көлеміне аздап байланысты.

Бір жобаның тарихы немесе мен Asterisk және Php негізіндегі АТС құруға 7 жыл жұмсадым

Нәтижесінде теру жоспарын әзірлеуге кететін уақыт айтарлықтай қысқарды және мен мұны бағалай аламын, өйткені PHP-дегі барлық модульдердің барлық теру жоспарын қайта жазуға тура келді. Біріншіден, мәліметтер базасынан нысанды алу үшін әдістер қазірдің өзінде PHP-де жазылуы керек; олар веб-интерфейсте көрсету үшін қажет болды, ал екіншіден, бұл ең бастысы, ақырында сандар мен массивтер бар жолдармен ыңғайлы жұмыс істеуге болады. дерекқормен және көптеген PHP кеңейтімдерімен.

Модуль класында теру жоспарын өңдеу үшін функцияны жүзеге асыру қажет dialplanDynamicCall және дәлел pbxCallRequest әрекеттесу үшін нысанды қамтиды Жұлдыздар.

Бір жобаның тарихы немесе мен Asterisk және Php негізіндегі АТС құруға 7 жыл жұмсадым

Сонымен қатар, теру жоспарын жөндеу мүмкін болды (php-де xdebug бар және ол біздің қызметіміз үшін жұмыс істейді), айнымалы мәндерді көру арқылы қадам бойынша жылжытуға болады.

Қоңырау деректері

Кез келген талдаулар мен есептер дұрыс жиналған деректерді қажет етеді және бұл АТС блогы да біріншіден үшінші нұсқаға дейін көптеген сынақтар мен қателіктерден өтті. Көбінесе қоңырау деректері белгі болып табылады. Бір қоңырау = бір жазба: кім қоңырау шалды, кім жауап берді, қанша уақыт сөйлесті. Неғұрлым қызықты нұсқаларда қоңырау кезінде қандай АТС қызметкері шақырылғанын көрсететін қосымша белгі бар. Бірақ мұның бәрі қажеттіліктердің бір бөлігін ғана қамтиды.

Бастапқы талаптар:

  • АТС кімге қоңырау шалғанын ғана емес, сонымен бірге кім жауап бергенін де сақтаңыз, өйткені ұстап алулар бар және оны қоңырауларды талдау кезінде ескеру қажет,
  • қызметкермен байланысуға дейінгі уақыт. жылы freepbx және кейбір басқа АТС-тер телефонды көтерген кезде қоңырауға жауап берілді деп саналады. Бірақ дауыстық мәзір үшін телефонды алу керек, сондықтан барлық қоңырауларға жауап беріледі және жауап күту уақыты 0-1 секундқа жетеді. Сондықтан жауапқа дейінгі уақытты ғана емес, негізгі модульдермен қосылуға дейінгі уақытты үнемдеу туралы шешім қабылданды (модульдің өзі бұл жалауды орнатады. Қазіргі уақытта ол «Қызметкер», «Сыртқы желі»),
  • күрделі теру жоспары үшін қоңырау әртүрлі топтар арасында өткенде, әрбір элементті бөлек қарастыру қажет болды.

Ең жақсы нұсқа АТС модульдері қоңыраулар кезінде өздері туралы ақпаратты жіберіп, соңында ақпаратты ағаш түрінде сақтаған кезде болды.

Бұл келесідей көрінеді:

Біріншіден, қоңырау туралы жалпы ақпарат (басқалар сияқты - ерекше ештеңе жоқ).

Бір жобаның тарихы немесе мен Asterisk және Php негізіндегі АТС құруға 7 жыл жұмсадым

  1. Сыртқы желіге қоңырау түсті »Сынақ үшін«05:55:52-де 89295671458 нөмірінен 89999999999 нөміріне, соңында қызметкер жауап берді»Хатшы 2» саны 104. Клиент 60 секунд күтіп, 36 секунд сөйледі.
  2. қызметкер»Хатшы 2«112 нөміріне қоңырау шалып, қызметкер жауап береді»Менеджер1» 8 секундтан кейін. Олар 14 секунд сөйлеседі.
  3. Клиент Қызметкерге беріледі »менеджер1«Онда олар тағы 13 секунд сөйлеседі

Бірақ бұл айсбергтің ұшы, әрбір жазба үшін сіз АТС арқылы толық қоңыраулар тарихын ала аласыз.

Бір жобаның тарихы немесе мен Asterisk және Php негізіндегі АТС құруға 7 жыл жұмсадым

Барлық ақпарат қоңыраулардың ұясы ретінде ұсынылады:

  1. Сыртқы желіге қоңырау түсті »Сынақ үшін» 05:55:52-де 89295671458 нөмірінен 89999999999 нөміріне дейін.
  2. Сағат 05:55:53-те сыртқы желі кіріс тізбегіне қоңырау жібереді »сынақ»
  3. Схема бойынша қоңырауды өңдеу кезінде модуль «менеджер шақыру", онда қоңырау 16 секундты құрайды. Бұл клиент үшін әзірленген модуль.
  4. Модуль»менеджер шақыру«нөмірге (клиентке) жауапты қызметкерге қоңырау жібереді»Менеджер1” деп таңдап, жауапты 5 секунд күтеді. Менеджер жауап бермеді.
  5. Модуль»менеджер шақыру«топқа қоңырау жібереді»CORP менеджерлері" Бұл бір бағыттағы басқа менеджерлер (бір бөлмеде отырады) және жауап үшін 11 секунд күтеді.
  6. Топ «CORP менеджерлері«қызметкерлерді шақырады»Менеджер1, Менеджер2, Менеджер3«бір уақытта 11 секунд. Жауап жоқ.
  7. Менеджердің қоңырауы аяқталады. Ал схема модульге қоңырау жібереді »1c бастап бағытты таңдау" Сондай-ақ клиент үшін жазылған модуль. Мұнда қоңырау 0 секундқа өңделді.
  8. Схема дауыстық мәзірге қоңырау жібереді »Қосымша теру арқылы негізгі" Клиент сонда 31 секунд күтті, қосымша теру болған жоқ.
  9. Схема Топқа қоңырау жібереді »Хатшылар«, мұнда клиент 12 секунд күтті.
  10. Топта бір уақытта 2 қызметкер шақырылады »Хатшы 1«Ал»Хатшы 2«және 12 секундтан кейін қызметкер жауап береді»Хатшы 2" Қоңырауға жауап ата-ана қоңырауларына қайталанады. Ол топта « деп жауап берген екен.Хатшы 2", қоңырау шалған кезде тізбек жауап берді"Хатшы 2" және сыртқы желідегі қоңырауға " деп жауап бердіХатшы 2«.

Бұл жай ғана есептерді шығаруға мүмкіндік беретін әрбір операция және олардың ұясы туралы ақпаратты сақтау. Дауыс мәзіріндегі есеп оның қаншалықты көмектесетінін немесе кедергі келтіретінін білуге ​​көмектеседі. Қоңыраудың ұсталғанын және сондықтан қабылданбаған деп есептелмейтінін және бұл топтық қоңырау болғанын және басқа біреудің бұрын жауап бергенін ескере отырып, қызметкерлер жіберіп алған қоңыраулар туралы есепті құрастырыңыз, бұл қоңырау да қабылданбағанын білдіреді.

Мұндай ақпаратты сақтау әр топты бөлек алып, оның қаншалықты тиімді жұмыс істейтінін анықтауға, жауап берген және жіберіп алған топтардың сағат бойынша графигін құруға мүмкіндік береді. Сондай-ақ басқарушыға қосылғаннан кейін аударымдарды талдау арқылы жауапты менеджерге қосылу қаншалықты дұрыс екенін тексеруге болады.

Сіз сондай-ақ өте типтік емес зерттеулер жүргізе аласыз, мысалы, дерекқорда жоқ нөмірлер дұрыс кеңейтімді тереді немесе шығыс қоңыраулардың қанша пайызы ұялы телефонға жіберіледі.

Ақырында не?

АТС-ке қызмет көрсету үшін маман қажет емес, оны ең қарапайым әкімші жасай алады - іс жүзінде тексерілген.

Модификациялар үшін күрделі біліктілігі бар мамандар қажет емес, PHP білімі жеткілікті, өйткені SIP хаттамасына, кезекке, қызметкерді шақыруға және т.б. үшін модульдер қазірдің өзінде жазылған. үшін орауыш класы бар Жұлдыздар. Модуль әзірлеу үшін бағдарламашы дайын модульдерді шақыра алады (және жақсы мағынада). Және білім Жұлдыздар егер клиент жаңа есеппен бет қосуды сұраса, мүлдем қажет емес. Бірақ тәжірибе көрсеткендей, үшінші тарап бағдарламашылары жеңе алса да, олар құжаттамасыз және түсініктемелердің қалыпты қамтылуынсыз өздерін қауіпсіз сезінеді, сондықтан әлі де жақсартуға мүмкіндік бар.

Модульдер:

  • жаңа қоңырауларды өңдеу мүмкіндіктерін жасау,
  • веб-интерфейске жаңа блоктарды қосу,
  • бар модульдердің кез келгенінен мұраға алу, функцияларды қайта анықтау және оны ауыстыру немесе сәл өзгертілген көшірме болу,
  • параметрлеріңізді басқа модульдердің параметрлер үлгісіне қосыңыз және т.б.

API арқылы PBX параметрлері. Жоғарыда сипатталғандай, барлық параметрлер дерекқорда сақталады және қоңырау шалу кезінде оқылады, сондықтан API арқылы барлық PBX параметрлерін өзгертуге болады. API шақырған кезде конфигурация қайта жасалмайды және модульдер қайта іске қосылмайды, сондықтан сізде қанша параметрлер мен қызметкерлердің болуы маңызды емес. API сұраулары жылдам орындалады және бір-бірін блоктамайды.

АТС ұзақтығы бар қоңыраулармен (күту/әңгімелесу), кірістірілген және АТС терминдерінде (арна, нөмір емес, қызметкер, топ, сыртқы желі) барлық негізгі операцияларды сақтайды. Бұл нақты клиенттер үшін әртүрлі есептерді құруға мүмкіндік береді және жұмыстың көпшілігі пайдаланушыға ыңғайлы интерфейсті жасау болып табылады.

Ары қарай не боларын уақыт көрсетеді. Қайта өңдеуді қажет ететін көптеген нюанстар бар, әлі де көптеген жоспарлар бар, бірақ 3-нұсқаның жасалғанына бір жыл өтті және идея жұмыс істеп жатыр деп айта аламыз. 3-нұсқаның негізгі кемшілігі аппараттық ресурстар болып табылады, бірақ бұл әдетте әзірлеудің қарапайымдылығы үшін төлеуге тура келетін нәрсе.

Ақпарат көзі: www.habr.com

пікір қалдыру