blob: d74d27eaf1e2a0d16768967bce22f614877ba665 [file] [log] [blame]
<?php
require_once("config.php");
class write {
public static function do($json) {
echo json_encode($json)."\n";
exit();
}
}
class conv {
public static function ask($msg_array) {
$items = array();
foreach ($msg_array as $msg) {
$items[] = array("simpleResponse" => array("textToSpeech" => $msg));
}
self::ask_custom($items);
}
public static function ask_followup($msg, &$i18n) {
self::ask([$msg, $i18n->msg("followup_".mt_rand(1, 3))]);
}
public static function ask_custom($items) {
$json = array();
$json["payload"] = array();
$json["payload"]["google"] = array();
$json["payload"]["google"]["expectUserResponse"] = true;
$json["payload"]["google"]["richResponse"] = array();
$json["payload"]["google"]["richResponse"]["items"] = $items;
write::do($json);
}
public static function has($item, &$json) {
foreach ($json["originalDetectIntentRequest"]["payload"]["surface"]["capabilities"] as $cap) {
if ($cap["name"] == $item) {
return true;
}
}
return false;
}
}
class i18n {
public static $hllist = array("en", "es");
public $i18n_strings = null;
public $language = null;
function __construct($lang) {
global $_GET;
global $conf;
if (empty($this->i18n_strings)) {
$this->i18n_strings = array();
}
$this->language = $lang;
$this->i18n_strings = json_decode(file_get_contents("assistant/".$this->language.".json"), true);
return true;
}
function msg($message, $strings = null) {
if (!isset($this->i18n_strings[$message])) {
return false;
}
$string = $this->i18n_strings[$message];
if ($strings != null && is_array($strings)) {
foreach ($strings as $i => $subst) {
$string = str_replace("{".$i."}", $subst, $string);
}
}
return $string;
}
}
function get_graph() {
global $conf;
return json_decode(file_get_contents($conf["apiurl"]), true);
}
function comma($array, $wait=false) {
global $i18n;
if (count($array) == 0) {
return "";
}
if (count($array) == 1) {
return $array[0];
}
$break = ($wait ? '<break time="0.5s"/>' : "");
return implode($break.", ", array_slice($array, 0, -1)).$break.", ".$i18n->msg("and")." ".$array[count($array)-1];
}
$json = json_decode(file_get_contents('php://input'), true);
if ($json === NULL || !isset($json["originalDetectIntentRequest"]) || !isset($json["originalDetectIntentRequest"]["source"]) || $json["originalDetectIntentRequest"]["source"] != "google") {
exit();
}
$graph = get_graph();
$lang = (isset($json["queryResult"]["languageCode"]) && in_array(substr($json["queryResult"]["languageCode"], 0, 2), i18n::$hllist) ? substr($json["queryResult"]["languageCode"], 0, 2) : "en");
$i18n = new i18n($lang);
switch ($json["queryResult"]["intent"]["displayName"]) {
case "showVertex":
if (!isset($json["queryResult"]["parameters"]["Vertex"])) {
exit();
}
$shortest = -1;
$closest = -1;
$closest_id = -1;
foreach ($graph["nodes"] as $id => $node) {
$lev = levenshtein(strtolower($json["queryResult"]["parameters"]["Vertex"]), strtolower($node["name"]));
if ($lev == 0) {
$closest = $node["name"];
$shortest = $lev;
$closest_id = $id;
}
if (($lev <= $shortest || $shortest < 0) && $lev <= 3) {
$closest = $node["name"];
$shortest = $lev;
$closest_id = $id;
}
}
if ($shortest != -1) {
$neighbors = array();
// 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.
foreach ($graph["edges"] as $edge) {
if ($edge["a"] == $closest_id) {
$neighbors[$graph["nodes"][$edge["b"]]["name"]] = $edge["votes"];
} elseif ($edge["b"] == $closest_id) {
$neighbors[$graph["nodes"][$edge["a"]]["name"]] = $edge["votes"];
}
}
if (count($neighbors) == 0) {
conv::ask_followup($i18n->msg("new_to_graph", array("person" => $closest)), $i18n);
} else {
arsort($neighbors);
$params = array("person" => $closest, "count" => (count($neighbors) == 1 ? $i18n->msg("count_singular") : $i18n->msg("count_plural", array("count" => count($neighbors)))));
if (conv::has("actions.capability.SCREEN_OUTPUT", $json)) {
$items = [
array(
"simpleResponse" => array(
"textToSpeech" => $i18n->msg("edges_display", $params)
)
),
array(
"tableCard" => array(
"columnProperties" => [
array(
"header" => "Adjacent vertex"
),
array("header" => "Votes")
],
"rows" => []
)
),
array(
"simpleResponse" => array(
"textToSpeech" => $i18n->msg("followup_".mt_rand(1, 3))
)
)
];
foreach ($neighbors as $neighbor => $votes) {
$items[1]["tableCard"]["rows"][] = array("cells" => [array("text" => $neighbor), array("text" => (string)$votes)]);
}
conv::ask_custom($items);
} else { // This code shows a table if the user has a screen, and
// as of now tables are finally public!
$people = array_keys($neighbors);
$people_string = comma($people);
$params["edges"] = $people_string;
$num = mt_rand(1, 3);
conv::ask_followup($i18n->msg("edges_".$num, $params), $i18n);
}
}
} else {
conv::ask_followup($i18n->msg("not_found", array("person" => $json["queryResult"]["parameters"]["Vertex"])), $i18n);
}
break;
case "randomFact":
$rand = mt_rand(0, 5);
switch ($rand) {
case 0: // Last edge in the graph
$last = array_values(array_slice($graph["edges"], -1))[0];
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);
break;
case 1: // Num vertices
conv::ask_followup($i18n->msg("didyouknow_num_vertices", array("count" => count($graph["nodes"]))), $i18n);
break;
case 2: // Num edges
conv::ask_followup($i18n->msg("didyouknow_num_edges", array("count" => count($graph["edges"]))), $i18n);
break;
case 3: // First 3 vertices K3
conv::ask_followup($i18n->msg("random_fact", array("fact" => $i18n->msg("didyouknow_k3"))), $i18n);
break;
case 4: // Creator
conv::ask_followup($i18n->msg("didyouknow_creator"), $i18n);
break;
case 5: // Groph
conv::ask_followup($i18n->msg("random_fact", array("fact" => $i18n->msg("didyouknow_groph"))), $i18n);
break;
}
break;
case "numVertexs":
conv::ask_followup($i18n->msg("num_vertices", array("count" => count($graph["nodes"]))), $i18n);
break;
case "numEdges":
conv::ask_followup($i18n->msg("num_edges", array("count" => count($graph["edges"]))), $i18n);
break;
case "latestNews":
$param = (isset($json["queryResult"]["parameters"]["numEdges"]) ? $json["queryResult"]["parameters"]["numEdges"] : null);
$num = (isset($param) && !empty($param) ? (int)$param : 4);
$last = array_values(array_slice($graph["edges"], -$num));
$edges = [];
foreach ($last as $edge) {
$edges[] = $graph["nodes"][$edge["a"]]["name"]." - ".$graph["nodes"][$edge["b"]]["name"];
}
$edges_string = comma($edges, true);
conv::ask_followup($i18n->msg((isset($param) && !empty($param) ? "latest_news_count" : "latest_news"), array("edges" => $edges_string, "count" => $num)), $i18n);
break;
default:
exit();
}