Important Announcement
PubHTML5 Scheduled Server Maintenance on (GMT) Sunday, June 26th, 2:00 am - 8:00 am.
PubHTML5 site will be inoperative during the times indicated!

Home Explore Tesi

Tesi

Published by bernardinello, 2018-11-22 06:07:49

Description: Tesi

Search

Read the Text Version

A.2. getMlt.php 4390 echo(\"curl_error: \" . curl_error($ch));91 curl_close($ch);92 return false;93 }94 curl_close($ch);95 if($risposta['responseHeader']['status']==0)96 return true;97 return false;98 } ?> A.2 getMlt.php A.2.1 Prima parte1 File getMlt.php2 <?php3 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); 45 global $db, $current_user;6 $userPref = new UserPreference($current_user); 78 //VALORI DI DEFAUL:9 $SAME_CLIENT_WEIGHT = 0.1; //di quanto favorisce i ticket dello stesso cliente10 $SAME_CAT_WEIGHT = 0.1; //di quanto favorisce i ticket della stessa categoria11 $MY_TEAM_WEIGHT = 0.1; //di quanto favorisce i ticket con lo stesso team12 $MAX_TICKET = 5; //quanti ticket simili visualizza13 $PREFER_RECENT = false; //se preferire i ticket recenti o meno1415 /*Contollo se i parametri di default sono stati cambiati da impostazioni,16 o se ci sono preferenze per l'utente:*/1718 if(isset($_REQUEST['max_ticket'])) {19 $MAX_TICKET = $_REQUEST['max_ticket'];20 $userPref->setPreference(\"max_ticket\", $MAX_TICKET);21 } else if(!is_null($userPref->getPreference(\"max_ticket\")))22 $MAX_TICKET=$userPref->getPreference(\"max_ticket\");2324 if(isset($_REQUEST['pref_same_client'])) {25 if(!strcmp($_REQUEST['pref_same_client'],'false'))26 $SAME_CLIENT_WEIGHT=0;27 $userPref->setPreference(\"same_client_weight\", $SAME_CLIENT_WEIGHT);28 } else if(!is_null($userPref->getPreference(\"same_client_weight\")))29 $SAME_CLIENT_WEIGHT=$userPref->getPreference(\"same_client_weight\");3031 if(isset($_REQUEST['pref_same_cat'])) {32 if(!strcmp($_REQUEST['pref_same_cat'],'false'))33 $SAME_CAT_WEIGHT = 0;34 $userPref->setPreference(\"same_cat_weight\", $SAME_CAT_WEIGHT);35 } else if(!is_null($userPref->getPreference(\"same_cat_weight\")))36 $SAME_CAT_WEIGHT=$userPref->getPreference(\"same_cat_weight\");37

44 Appendice A. Codice sorgente38 if(isset($_REQUEST['pref_my_team'])) {39 if(!strcmp($_REQUEST['pref_my_team'], 'false'))40 $MY_TEAM_WEIGHT = 0;41 $userPref->setPreference(\"my_team_weight\", $MY_TEAM_WEIGHT);42 } else if(!is_null($userPref->getPreference(\"my_team_weight\")))43 $MY_TEAM_WEIGHT=$userPref->getPreference(\"my_team_weight\");4445 if(isset($_REQUEST['prefer_recent'])) {46 $PREFER_RECENT = (!strcmp($_REQUEST['prefer_recent'],'true'));47 $userPref->setPreference(\"prefer_recent\", $PREFER_RECENT);48 } else if(!is_null($userPref->getPreference(\"prefer_recent\")))49 $PREFER_RECENT=$userPref->getPreference(\"prefer_recent\");5051 /*Scrivo le preferenze nella pagina in modo da poterle legggere dal JS52 e visualizzarle nel pannello di impostazioni: */53 echo(\"<input type='hidden' id='max_ticket' value='$MAX_TICKET'/>\");54 echo(\"<input type='hidden' id='prefer_recent' value='\".55 json_encode($PREFER_RECENT) .\"'/>\");56 echo(\"<input type='hidden' id='pref_same_cat' value='\".57 json_encode($SAME_CAT_WEIGHT>0) .\"'/>\");58 echo(\"<input type='hidden' id='pref_same_client' value='\".59 json_encode($SAME_CLIENT_WEIGHT>0).\"'/>\");60 echo(\"<input type='hidden' id='pref_my_team' value='\".61 json_encode($MY_TEAM_WEIGHT>0).\"'/>\");62 // Se non è definito l'id del ticket lo imposto a null63 $id_ticket = isset($_REQUEST['id_ticket']) ? $_REQUEST['id_ticket'] : null;64 //forza l'aggiornamento della cache:65 $refreshCache = isset($_REQUEST['refreshCache'])?$_REQUEST['refreshCache']:false;66 //definisce se usare o meno la cache:67 $CACHE_ON = isset($_REQUEST['cacheOn']) ? $_REQUEST['cacheOn'] : true; A.2.2 Seconda parte1 File getMlt.php2 <?php3 ...4 if(!is_null($id_ticket) && $id_ticket!=='null' && $id_ticket!=='undefined') {5 $CACHE_PATH = getcwd() . '/modules/MCE_CsDemands/cacheMlt/';6 /* percorso/del/file/in/cache/ID.json,7 uso come nome del file l'id del ticket:*/8 $fileCachePath = $CACHE_PATH.$id_ticket.'.json';9 if($CACHE_ON && !$refreshCache && file_exists($fileCachePath)) {10 //uso il json in cache:11 $jsonRead = file_get_contents($fileCachePath);12 $jsonArray = json_decode($jsonRead, true);13 }14 else {15 // *RICHIESTA MLT A SOLR16 $jsonArray = ...17 }18

A.2. getMlt.php 4519 if ($jsonArray!==false) {20 if(!is_null($jsonArray)) {21 if ($jsonArray['response']['numFound'] > 0) {22 /* *RICALCOLO LO SCORE,23 RISPONDO CON LA LISTA DEI TICKET24 e SALVO IL JSON IN CACHE*/25 }26 else { //numfound = 027 echo(\"<br>&emsp;Spiacenti,28 non c'è nessun ticket correlato.\");29 }30 } else { //Json ritornato = null31 echo(\"<br>Errore: Json ritornato da Solr null.\");32 }33 } else { //Curl error34 echo(\"<br>Si è verificato un errore durante la richiesta a Solr.\");35 }36 } else { //id_ticket null o undefined37 echo('<br>Id ticket non valido. (id null o undefined)');38 } A.2.3 Richiesta MLT a Solr1 File getMlt.php - *RICHIESTA MLT A SOLR2 <?php3 ...4 if($CACHE_ON && !$refreshCache && file_exists($fileCachePath)) {5 ...6}7 else { // *RICHIESTA MLT A SOLR8 //Ottengo dal db i dati del ticket passato (testo, categoria,...)9 $q=\"SELECT users.default_team, mce_csdemands.parent_id,10 mce_csdemands.description,11 mce_checktreedoms.id AS mce_checktreedoms_id,12 mce_checktreedoms.parent_node FROM mce_csdemands13 INNER JOIN mce_csdemand_mce_checktreedom14 ON mce_csdemands.id=mce_csdemand_mce_checktreedom.record_id15 INNER JOIN mce_checktreedoms16 ON mce_csdemand_mce_checktreedom.checktreedom_id=mce_checktreedoms.id17 INNER JOIN users ON users.id='$current_user->id'18 WHERE mce_csdemands.id='$id_ticket'\";1920 $db_result = $db->query($q);21 $elencoCat = []; //tutte le categorie in cui è inserito il ticket22 $testo = '';23 while($row = $db->fetchByAssoc($db_result) ) {24 /*nella descrizione sono presenti25 \"=== admin (Administrator) - 07/03/2018 15:50 ===\",26 che vanno rimossi:*/27 $testo = preg_replace('/(===)(.*)(===)/', '',28 $row['description']);

46 Appendice A. Codice sorgente29 $id_azienda=$row['parent_id']; //tabella account30 //team (securitygroup) dell'utente:31 $default_team = $row['default_team'];32 /*contiene tutte le categorie in cui è presente33 il ticket (dalla più generica alla più interna)34 con i rispettivi padri:*/35 array_push($elencoCat, [36 'id'=>$row['mce_checktreedoms_id'],37 'parent_node'=>$row['parent_node'],38 ]);39 }40 //ricreo la gerarchia delle categorie:41 foreach($elencoCat as $nodo)42 if($nodo['parent_node']=='')43 $id_categoria1 = $nodo['id']; //categoria più generica44 foreach($elencoCat as $nodo)45 if(!is_null($id_categoria1) &&46 !strcmp($nodo['parent_node'],$id_categoria1))47 $id_categoria2 = $nodo['id'];48 foreach($elencoCat as $nodo)49 if(!is_null($id_categoria2) &&50 !strcmp($nodo['parent_node'], $id_categoria2))51 $id_categoria3 = $nodo['id']; //categoria più interna52 $jsonArray = sendMltJson($testo); A.2.4 Invio risposta1 <?php2 File getMlt.php3 ...4 /* *RICALCOLO LO SCORE,5 RISPONDO CON LA LISTA DEI TICKET6 e SALVO IL JSON IN CACHE*/7 if ($jsonArray['response']['numFound'] > 0) {8 $docs = $jsonArray['response']['docs']; //array di ticket9 $rilevanti_array=[];10 $punteggi_modificati=false;1112 foreach($docs as $doc ) {13 $id = $doc['id'];14 $description= $doc['description'];15 $score = $doc['score'];16 $name = $doc['name'];17 $date_entered = new DateTime($doc['de_year'] .18 \"-\".$doc['de_month'].19 \"-\".$doc['de_day'],20 new DateTimeZone('Europe/Rome'));21 if($PREFER_RECENT) {22 $interval = date_diff(new DateTime(), $date_entered);23 //di quanti giorni è vecchio il ticket:24 $giorni_old = $interval->days;

A.2. getMlt.php 4725 $score += 365/($giorni_old+365);26 $punteggi_modificati=true;27 }28 if(is_string($doc['parent_id']) &&29 !strcmp($doc['parent_id'], $id_azienda)) {30 $score+=$SAME_CLIENT_WEIGHT;31 $punteggi_modificati=true;32 }33 //categorie:34 if(is_string($doc['id_cat3']) &&35 !strcmp($doc['id_cat3'], $id_categoria3)) {36 $score+=$SAME_CAT_WEIGHT*3;37 $punteggi_modificati=true;38 } else if(is_string($doc['id_cat2']) &&39 !strcmp($doc['id_cat2'], $id_categoria2)) {40 $score+=$SAME_CAT_WEIGHT*2;41 $punteggi_modificati=true;42 } else if(is_string($doc['id_cat1']) &&43 !strcmp($doc['id_cat1'], $id_categoria1)) {44 $score+=$SAME_CAT_WEIGHT;45 $punteggi_modificati=true;46 }47 //i team degli utenti che hanno contribuito:48 if(in_array($default_team, $doc['securitygroups'])) {49 $score+=$MY_TEAM_WEIGHT;50 $punteggi_modificati=true;51 }5253 $doc_array = [ \"id\"=> $id,54 \"description\" => $description,55 \"score\" => $score,56 \"name\" => $name,57 \"date_entered\"=>$date_entered58 ];59 //dettagli che verranno visualizzati a video per ogni ticket60 array_push($rilevanti_array, $doc_array);61 }62 if($punteggi_modificati)63 uasort($rilevanti_array, 'compare_score');64 $rilevanti_array = array_slice($rilevanti_array, 0, $MAX_TICKET);65 $linkReturn='';66 foreach($rilevanti_array as $ticket){ //Scrive sulla pagina la risposta67 $linkReturn .= '<tr><td><a href=\"index.php?68 module=MCE_CsDemands&action=DetailView&record='.69 $ticket['id'].'\">'.$ticket['name'].70 '</a> - ' .$ticket['description']. ' </td>';71 $linkReturn .= '<td>Del '.72 $ticket['date_entered']->format('d/m/Y') .'</td></tr>';73 }74 $linkReturn = $linkReturn . '&emsp;Aggiornato al ' .75 $jsonArray['lastUpdate'];

48 Appendice A. Codice sorgente76 echo($linkReturn);77 if($CACHE_ON) {78 if(!file_exists($CACHE_PATH))79 mkdir($CACHE_PATH);80 if(count(scandir($CACHE_PATH))>250)81 //mantengo al massimo 250 files in cache82 foreach(scandir($CACHE_PATH) as $file)83 unlink($CACHE_PATH . $file);84 if(!file_exists($fileCachePath) || $refreshCache) {85 $stringJson = json_encode($jsonArray);86 file_put_contents($fileCachePath, $stringJson);87 }88 }89 } A.3 Soluzione non realizzata1 <?php2 require_once('Phpml\Transformer.php');3 require_once('Phpml\Tokenization\Tokenizer.php');4 require_once('Phpml\FeatureExtraction\TokenCountVectorizer.php');5 require_once('Phpml\FeatureExtraction\StopWords.php');6 require_once('Phpml\Tokenization\WordTokenizer.php');7 require_once('Phpml\FeatureExtraction\TfIdfTransformer.php');8 require_once('Phpml\Similarity.php'); 910 $testi = []; //contiene le descrizioni di tutti i ticket11 $meta = []; //contiene i metadati dei ticket1213 $SAME_CLIENT_WEIGHT = 0.1; //di quanto favorisce i ticket dello stesso cliente14 $SAME_CAT_WEIGHT = 0.1; //di quanto favorisce i ticket della stessa categoria15 $MAX_RELATED_TICKET = 5; //quanti ticket simili ritorna1617 $q = \"SELECT * FROM mce_csdemands18 WHERE description IS NOT NULL AND resolution IS NOT NULL19 AND deleted=0 AND kb=true\"; //flag knowledge base2021 $r = $db->query($q);22 while($a = $db->fetchByAssoc($r)) {23 if(strlen($a['description'])>0) {24 array_push($testi, strtolower($a['description'] . ' ' . $a['resolution']));25 array_push($meta, [26 'id' => $a['id'],27 'cliente'=> $a['account_id'],28 'categoria'=> $a['mce_checktreedoms_id'],29 'testo'=> substr($a['description'],0,150).'...',30 ]);31 }32 }33

A.3. Soluzione non realizzata 4934 $stopWordsArray = ['l\'','la','a','ad', ... ];3536 /*trasformo l'array dei testi in array di vettori37 bag-of-words (contenenti la frequenza di ogni parola)*/38 $vectorizer = new TokenCountVectorizer(39 new WordTokenizer(),40 new StopWords($stopWordsArray), 2); //min doc. frequency=24142 $vectorizer->fit($testi);43 $vectorizer->transform($testi);4445 //trasformo ogni vettore bag of words con i punteggi tf-idf:46 $transformer = new TfIdfTransformer($testi);47 $transformer->transform($testi);4849 //ottengo i dettagli del ticket visualizzato:50 $ticket = ... ; //query al database, omessa per semplicità5152 $testo=[$ticket['description']]; //(transform() accetta solo array)53 //ottengo il vettore tfidf del testo da ricercare:54 $vectorizer->transform($testo);55 $transformer->transform($testo);56 $maxSim=0;57 //cerco il migliore tramite similitudine di coseno58 (punteggio alto=similitudine alta)59 $trovati=[]; //array mantenuto ordinato in base al punteggio di similitudine,60 contiene id=>sim61 foreach($testi as $i=>$vect) {62 $sim = Similarity::cosine($vect, $testo);63 if(!strcmp($ticket['cliente'], $meta[$i]['cliente']))64 $sim+=$SAME_CLIENT_WEIGHT;65 if(!strcmp($ticket['categoria'], $meta[$i]['categoria']))66 $sim+=$SAME_CAT_WEIGHT; //l'ultimo elemento avrà similitudine minima67 $details = [68 'id'=> $meta[$i]['id'],69 'sim'=>$sim,70 'testo'=>$meta[$i]['testo']71 ];72 array_push($trovati, $details);73 }74 uasort($trovati, 'compare_sim');75 //mantiene i migliori MAX_RELATED_TICKET:76 $trovati = array_slice($trovati, 0, $MAX_RELATED_TICKET);7778 foreach($trovati as $k=>$v) {79 echo('<a href=\"index.php?module=MCE_CsDemands&action=DetailView&record='.80 $v['id'].'\">'.$v['testo'].'</a><br>');81 }82 function compare_sim($a, $b) {83 if ($a['sim']==$b['sim'])84 return 0;

50 Appendice A. Codice sorgente85 return ($a['sim']>$b['sim'])? -1:1;86 }87 ?> A.4 Pannello di impostazioni in JavaScript1 var settingsPanel;2 function showSettings() {3 var maxTicketTitle = \"Ticket da visualizzare\";4 var recentTitle = \"Più recenti\";5 var catTitle = \"Della stessa tipologia\";6 var clientTitle = \"Dallo stello cliente\";7 var mioTeamTitle = \"Risolti dal mio team\"; 89 if(settingsPanel==null)10 settingsPanel = QuickSettings.create($(window).width()/2,11 $(window).height()/2, \"Impostazioni\")12 .addHTML(\"Favorisci i ticket...\", \"\")13 .addBoolean(recentTitle,14 JSON.parse(document.getElementById(\"prefer_recent\").value),15 function(value) {})16 .addBoolean(catTitle,17 JSON.parse(document.getElementById(\"pref_same_cat\").value),18 function(value) {})19 .addBoolean(clientTitle,20 JSON.parse(document.getElementById(\"fav_same_client\").value),21 function(value) {})22 .addBoolean(mioTeamTitle,23 JSON.parse(document.getElementById(\"pref_my_team\").value),24 function(value) {})25 .addRange(maxTicketTitle, 3, 10,26 document.getElementById(\"max_ticket\").value, 1,27 function(value) {})28 .addButton(\"Ok\", function(value) {29 var params='';30 params+= \"&max_ticket=\"+ settingsPanel.getValue(maxTicketTitle);31 params+= \"&fav_same_client=\"+ settingsPanel.getValue(clientTitle);32 params+= \"&pref_same_cat=\"+ settingsPanel.getValue(catTitle);33 params+= \"&prefer_recent=\"+ settingsPanel.getValue(recentTitle);34 params+= \"&pref_my_team=\"+ settingsPanel.getValue(mioTeamTitle);35 sendMlt(params);36 settingsPanel.hide();37 })38 .addButton(\"Annulla\", function(value) {39 settingsPanel.hide();40 });41 settingsPanel.show();42 }

A.5. DetailView con Smarty 51 A.5 DetailView con Smarty1 <div id='detailpanel_7' class='detail view detail508 expanded'>2 <script type=\"text/javascript\"3 src=\"modules/MCE_CsDemands/jssource/quicksettings/quicksettings.js\"></script>4 <script src=\"modules/MCE_CsDemands/jssource/requestMlt.js\"></script>5 <h4>6 <a href=\"javascript:void(0)\" class=\"collapseLink\" onclick=\"collapsePanel(7);\">7 <img border=\"0\" id=\"detailpanel_7_img_hide\"8 src=\"themes/MCE_White2/images/basic_search.gif\">9 </a>10 <a href=\"javascript:void(0)\" class=\"expandLink\" onclick=\"expandPanel(7);\">11 <img border=\"0\" id=\"detailpanel_7_img_show\"12 src=\"themes/MCE_White2/images/advanced_search.gif\">13 </a>14 Ticket Correlati15 <a href=\"javascript:void(0)\" onclick=\"sendMlt('&refreshCache=true');\">16 <img src=\"themes/MCE_White2/images/dashlet-header-refresh.png\"17 border=\"0\" align=\"absmiddle\" alt=\"Aggiorna\">18 </a>19 <a href=\"javascript:void(0)\" onclick=\"showSettings();\">20 <img src=\"themes/MCE_White2/images/dashlet-header-edit.png\"21 border=\"0\" align=\"absmiddle\" alt=\"Impostazioni\">22 </a>23 </h4>24 <table class=\"panelContainer\" cellspacing='{$gridline}' id=\"correlatiTable\">25 <script type=\"text/javascript\">sendMlt('');</script>26 </table>27 </div>



53Bibliografia [1] Joeran Beel et al. «Research-paper recommender systems: a literature survey». In: International Journal on Digital Libraries (2016), p. 319. URL: https://kops. uni- konstanz.de/bitstream/handle/123456789/32348/Beel_0- 311312. pdf. [2] Hans Peter Luhn. «A Statistical Approach to Mechanized Encoding and Sear- ching of Literary Information». In: BM Journal of Research and Development (1957), p. 315. URL: http://web.stanford.edu/class/linguist289/luhn57.pdf. [3] Christopher D. Manning, Prabhakar Raghavan e Hinrich Schütze. «Introduc- tion to Information Retrieval». In: Cambridge University Press (2009). URL: https: //nlp.stanford.edu/IR-book/pdf/irbookonlinereading.pdf. La citazione in prima pagina è tratta dal capitolo 8.5 a pagina 185. [4] «A Statistical Interpretation of Term Specificity and Its Application in Retrie- val». In: Journal of Documentation (1972). URL: http://citeseerx.ist.psu. edu/viewdoc/summary?doi=10.1.1.115.8343. [5] Raffaella Bernardi. «Term Frequency and Inverse Document Frequency». In: Università di Trento (2011-2012). URL: http : / / disi . unitn . it / ~bernardi / Courses/DL/Slides_11_12/measures.pdf. [6] G.Salton, A. Wong e C.S. Yang. «A Vector Space Model for Automatic Inde- xing». In: Cornell University (1975), pp. 613–620. URL: http://citeseerx.ist. psu.edu/viewdoc/download?doi=10.1.1.446.5101&rep=rep1&type=pdf. [7] Apache server. URL: https://httpd.apache.org/. [8] PHP. URL: https://php.net/. [9] W3Techs. Usage statistics and market share of PHP for websites. URL: https:// w3techs.com/technologies/details/pl-php/all/all.[10] Mozilla. JavaScript. URL: https://developer.mozilla.org/it/docs/Web/ JavaScript.[11] JSON. URL: https://json.org/.[12] MySql. URL: https://www.mysql.com/.[13] Visual Studio Code. URL: https://code.visualstudio.com/.[14] Estensione ftp-kr per Visual Studio Code. URL: https://marketplace.visualstudio. com/items?itemName=ruakr.ftp-kr.[15] StackOverflow. Most Popular Development Environments. 2018. URL: https:// insights . stackoverflow . com / survey / 2018 # technology - most - popular - development-environments.[16] OpenSymbol. CRM: cos’è e a che cosa serve. 2014. URL: https://www.opensymbol. it/crm-cosa-e-a-cosa-serve/.[17] SuiteCRM. URL: https://suitecrm.com/.[18] SpiceCRM. URL: http://www.spicecrm.io/.

54 BIBLIOGRAFIA[19] Smarty. URL: https://www.smarty.net/.[20] Apache Solr. URL: https://lucene.apache.org/solr/.[21] QuickSettings. URL: https://github.com/bit101/quicksettings.[22] PHP-ML. URL: https://github.com/php-ai/php-ml.[23] Token Count Vectorizer. URL: https://php- ml.readthedocs.io/en/latest/ machine-learning/feature-extraction/token-count-vectorizer/.

RingraziamentiSeppur individuale, una laurea è un cammino che si percorre con il supporto di piùpersone. Giunti ormai al termine, è il momento giusto per ringraziare chi hacontribuito, direttamente o meno, al raggiungimento di questo traguardo.Ringrazio il professor Carlo Fantozzi per essere stato una preziosa guida durante ilperiodo di tirocinio e la stesura di questa relazione, dimostrando una completa edamichevole disponibilità che ne ha reso piacevole la collaborazione.Ringrazio i miei genitori, Monica e Mauro, e i miei nonni, Maria e Demetrio, che mihanno regalato il miglior investimento possibile per il mio futuro, altrimentiimpossibile senza il loro aiuto.Ringrazio i miei compagni di università che hanno condiviso con me le fatiche, ledelusioni e le soddisfazioni che questo percorso ci ha portato e si sono trasformatiin grandi amici con cui condividere mille avventure.Ad altre mille ancora.Agradezco la Universidad de Cantabria por haber sido mi casa para cinco meses, ytodos aquellos que han hecho mi erasmus en Santander tan único y lleno deemociones y recuerdos que no se pueden describir, sino solamente vivir.Ringrazio tutti gli amici e le amiche, vicini e lontani, che mi hanno accompagnato inquesti tre anni offrendomi sempre un consiglio, un incoraggiamento o una risata.Ringrazio anche chi ad un certo punto se n’è andato, ma per un periodo c’è stato.Ringrazio infine quel ragazzino appassionato di informatica per non aver maismesso di inseguire il suo obiettivo e che ora, finalmente, lo ha raggiunto. Padova, 26 novembre 2018


Like this book? You can publish your book online for free in a few minutes!
Create your own flipbook