avm99963 | cbcae35 | 2018-09-26 16:16:37 +0200 | [diff] [blame] | 1 | <?php |
| 2 | require_once("config.php"); |
| 3 | |
| 4 | class write { |
| 5 | public static function do($json) { |
| 6 | echo json_encode($json)."\n"; |
| 7 | exit(); |
| 8 | } |
| 9 | } |
| 10 | |
| 11 | class conv { |
| 12 | public static function ask($msg_array) { |
| 13 | $items = array(); |
| 14 | |
| 15 | foreach ($msg_array as $msg) { |
| 16 | $items[] = array("simpleResponse" => array("textToSpeech" => $msg)); |
| 17 | } |
| 18 | |
| 19 | self::ask_custom($items); |
| 20 | } |
| 21 | |
| 22 | public static function ask_followup($msg, &$i18n) { |
| 23 | self::ask([$msg, $i18n->msg("followup_".mt_rand(1, 3))]); |
| 24 | } |
| 25 | |
| 26 | public static function ask_custom($items) { |
| 27 | $json = array(); |
| 28 | $json["payload"] = array(); |
| 29 | $json["payload"]["google"] = array(); |
| 30 | $json["payload"]["google"]["expectUserResponse"] = true; |
| 31 | $json["payload"]["google"]["richResponse"] = array(); |
| 32 | $json["payload"]["google"]["richResponse"]["items"] = $items; |
| 33 | |
| 34 | write::do($json); |
| 35 | } |
| 36 | |
| 37 | public static function has($item, &$json) { |
| 38 | foreach ($json["originalDetectIntentRequest"]["payload"]["surface"]["capabilities"] as $cap) { |
| 39 | if ($cap["name"] == $item) { |
| 40 | return true; |
| 41 | } |
| 42 | } |
| 43 | return false; |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | class i18n { |
| 48 | public static $hllist = array("en", "es"); |
| 49 | public $i18n_strings = null; |
| 50 | public $language = null; |
| 51 | |
| 52 | function __construct($lang) { |
| 53 | global $_GET; |
| 54 | global $conf; |
| 55 | |
| 56 | if (empty($this->i18n_strings)) { |
| 57 | $this->i18n_strings = array(); |
| 58 | } |
| 59 | |
| 60 | $this->language = $lang; |
| 61 | |
| 62 | $this->i18n_strings = json_decode(file_get_contents("assistant/".$this->language.".json"), true); |
| 63 | |
| 64 | return true; |
| 65 | } |
| 66 | |
| 67 | function msg($message, $strings = null) { |
| 68 | if (!isset($this->i18n_strings[$message])) { |
| 69 | return false; |
| 70 | } |
| 71 | |
| 72 | $string = $this->i18n_strings[$message]; |
| 73 | |
| 74 | if ($strings != null && is_array($strings)) { |
| 75 | foreach ($strings as $i => $subst) { |
| 76 | $string = str_replace("{".$i."}", $subst, $string); |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | return $string; |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | function get_graph() { |
| 85 | global $conf; |
| 86 | return json_decode(file_get_contents($conf["apiurl"]), true); |
| 87 | } |
| 88 | |
| 89 | function comma($array, $wait=false) { |
| 90 | global $i18n; |
| 91 | if (count($array) == 0) { |
| 92 | return ""; |
| 93 | } |
| 94 | if (count($array) == 1) { |
| 95 | return $array[0]; |
| 96 | } |
| 97 | $break = ($wait ? '<break time="0.5s"/>' : ""); |
| 98 | return implode($break.", ", array_slice($array, 0, -1)).$break.", ".$i18n->msg("and")." ".$array[count($array)-1]; |
| 99 | } |
| 100 | |
| 101 | $json = json_decode(file_get_contents('php://input'), true); |
| 102 | |
| 103 | if ($json === NULL || !isset($json["originalDetectIntentRequest"]) || !isset($json["originalDetectIntentRequest"]["source"]) || $json["originalDetectIntentRequest"]["source"] != "google") { |
| 104 | exit(); |
| 105 | } |
| 106 | |
| 107 | $graph = get_graph(); |
| 108 | $lang = (isset($json["queryResult"]["languageCode"]) && in_array(substr($json["queryResult"]["languageCode"], 0, 2), i18n::$hllist) ? substr($json["queryResult"]["languageCode"], 0, 2) : "en"); |
| 109 | $i18n = new i18n($lang); |
| 110 | |
| 111 | switch ($json["queryResult"]["intent"]["displayName"]) { |
| 112 | case "showVertex": |
| 113 | if (!isset($json["queryResult"]["parameters"]["Vertex"])) { |
| 114 | exit(); |
| 115 | } |
| 116 | |
| 117 | $shortest = -1; |
| 118 | $closest = -1; |
| 119 | $closest_id = -1; |
| 120 | |
| 121 | foreach ($graph["nodes"] as $id => $node) { |
| 122 | $lev = levenshtein(strtolower($json["queryResult"]["parameters"]["Vertex"]), strtolower($node["name"])); |
| 123 | |
| 124 | if ($lev == 0) { |
| 125 | $closest = $node["name"]; |
| 126 | $shortest = $lev; |
| 127 | $closest_id = $id; |
| 128 | } |
| 129 | |
| 130 | if (($lev <= $shortest || $shortest < 0) && $lev <= 3) { |
| 131 | $closest = $node["name"]; |
| 132 | $shortest = $lev; |
| 133 | $closest_id = $id; |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | if ($shortest != -1) { |
| 138 | $neighbors = array(); |
| 139 | // We're suposing each vertex has a different name. If not, this would get rid of some of the edges, but if two vertexs had the same name there would be no way to differentiate them anyway, so I think it's ok. |
| 140 | foreach ($graph["edges"] as $edge) { |
| 141 | if ($edge["a"] == $closest_id) { |
| 142 | $neighbors[$graph["nodes"][$edge["b"]]["name"]] = $edge["votes"]; |
| 143 | } elseif ($edge["b"] == $closest_id) { |
| 144 | $neighbors[$graph["nodes"][$edge["a"]]["name"]] = $edge["votes"]; |
| 145 | } |
| 146 | } |
| 147 | if (count($neighbors) == 0) { |
| 148 | conv::ask_followup($i18n->msg("new_to_graph", array("person" => $closest)), $i18n); |
| 149 | } else { |
| 150 | arsort($neighbors); |
| 151 | $params = array("person" => $closest, "count" => (count($neighbors) == 1 ? $i18n->msg("count_singular") : $i18n->msg("count_plural", array("count" => count($neighbors))))); |
avm99963 | 691c2bf | 2018-10-18 22:55:09 +0200 | [diff] [blame^] | 152 | if (conv::has("actions.capability.SCREEN_OUTPUT", $json)) { |
avm99963 | cbcae35 | 2018-09-26 16:16:37 +0200 | [diff] [blame] | 153 | $items = [ |
| 154 | array( |
| 155 | "simpleResponse" => array( |
| 156 | "textToSpeech" => $i18n->msg("edges_display", $params) |
| 157 | ) |
| 158 | ), |
| 159 | array( |
| 160 | "tableCard" => array( |
| 161 | "columnProperties" => [ |
| 162 | array( |
| 163 | "header" => "Adjacent vertex" |
| 164 | ), |
| 165 | array("header" => "Votes") |
| 166 | ], |
| 167 | "rows" => [] |
| 168 | ) |
| 169 | ), |
| 170 | array( |
| 171 | "simpleResponse" => array( |
| 172 | "textToSpeech" => $i18n->msg("followup_".mt_rand(1, 3)) |
| 173 | ) |
| 174 | ) |
| 175 | ]; |
| 176 | foreach ($neighbors as $neighbor => $votes) { |
| 177 | $items[1]["tableCard"]["rows"][] = array("cells" => [array("text" => $neighbor), array("text" => (string)$votes)]); |
| 178 | } |
| 179 | conv::ask_custom($items); |
avm99963 | 691c2bf | 2018-10-18 22:55:09 +0200 | [diff] [blame^] | 180 | } else { // This code shows a table if the user has a screen, and |
| 181 | // as of now tables are finally public! |
avm99963 | cbcae35 | 2018-09-26 16:16:37 +0200 | [diff] [blame] | 182 | $people = array_keys($neighbors); |
| 183 | $people_string = comma($people); |
| 184 | $params["edges"] = $people_string; |
| 185 | $num = mt_rand(1, 3); |
| 186 | conv::ask_followup($i18n->msg("edges_".$num, $params), $i18n); |
avm99963 | 691c2bf | 2018-10-18 22:55:09 +0200 | [diff] [blame^] | 187 | } |
avm99963 | cbcae35 | 2018-09-26 16:16:37 +0200 | [diff] [blame] | 188 | } |
| 189 | } else { |
| 190 | conv::ask_followup($i18n->msg("not_found", array("person" => $json["queryResult"]["parameters"]["Vertex"])), $i18n); |
| 191 | } |
| 192 | break; |
| 193 | |
| 194 | case "randomFact": |
| 195 | $rand = mt_rand(0, 5); |
| 196 | switch ($rand) { |
| 197 | case 0: // Last edge in the graph |
| 198 | $last = array_values(array_slice($graph["edges"], -1))[0]; |
| 199 | conv::ask_followup($i18n->msg("random_fact", array("fact" => $i18n->msg("didyouknow_last_edge", array("person1" => $graph["nodes"][$last["a"]]["name"], "person2" => $graph["nodes"][$last["b"]]["name"])))), $i18n); |
| 200 | break; |
| 201 | |
| 202 | case 1: // Num vertices |
| 203 | conv::ask_followup($i18n->msg("didyouknow_num_vertices", array("count" => count($graph["nodes"]))), $i18n); |
| 204 | break; |
| 205 | |
| 206 | case 2: // Num edges |
| 207 | conv::ask_followup($i18n->msg("didyouknow_num_edges", array("count" => count($graph["edges"]))), $i18n); |
| 208 | break; |
| 209 | |
| 210 | case 3: // First 3 vertices K3 |
| 211 | conv::ask_followup($i18n->msg("random_fact", array("fact" => $i18n->msg("didyouknow_k3"))), $i18n); |
| 212 | break; |
| 213 | |
| 214 | case 4: // Creator |
| 215 | conv::ask_followup($i18n->msg("didyouknow_creator"), $i18n); |
| 216 | break; |
| 217 | |
| 218 | case 5: // Groph |
| 219 | conv::ask_followup($i18n->msg("random_fact", array("fact" => $i18n->msg("didyouknow_groph"))), $i18n); |
| 220 | break; |
| 221 | } |
| 222 | |
| 223 | break; |
| 224 | |
| 225 | case "numVertexs": |
| 226 | conv::ask_followup($i18n->msg("num_vertices", array("count" => count($graph["nodes"]))), $i18n); |
| 227 | break; |
| 228 | |
| 229 | case "numEdges": |
| 230 | conv::ask_followup($i18n->msg("num_edges", array("count" => count($graph["edges"]))), $i18n); |
| 231 | break; |
| 232 | |
| 233 | case "latestNews": |
| 234 | $param = (isset($json["queryResult"]["parameters"]["numEdges"]) ? $json["queryResult"]["parameters"]["numEdges"] : null); |
| 235 | $num = (isset($param) && !empty($param) ? (int)$param : 4); |
| 236 | $last = array_values(array_slice($graph["edges"], -$num)); |
| 237 | $edges = []; |
| 238 | foreach ($last as $edge) { |
| 239 | $edges[] = $graph["nodes"][$edge["a"]]["name"]." - ".$graph["nodes"][$edge["b"]]["name"]; |
| 240 | } |
| 241 | $edges_string = comma($edges, true); |
| 242 | conv::ask_followup($i18n->msg((isset($param) && !empty($param) ? "latest_news_count" : "latest_news"), array("edges" => $edges_string, "count" => $num)), $i18n); |
| 243 | break; |
| 244 | |
| 245 | default: |
| 246 | exit(); |
| 247 | } |