<?php
/**
*
* Minor extension to base Api_RadarisGo
*
* Use specific server for $api->fl_pop and $api->name_pop queries
* This queries requires a lot of memory (huge file loaded on-demand)
*
* Query Removals: return REMOVED items only
* php> i('go-api.name-server')->removals([1147056740357836278, 165050511284695997, 16505051128469])
* Array(
* 1147056740357836278 => 1
* 165050511284695997 => $REASON
* )
*
* FULL RELOAD
* php> i('go-api.name-server')->removalsReload(1)
* Array( 0 => OK )
* Time: 12,277ms << SLOW
*
* LOAD NEW RECORDS ONLY - (FAST)
* php> i('go-api.name-server')->removalsReload(0)
* Array( 0 => OK )
*
*/
class Api_RadarisGo_NameServer extends Api_RadarisGo {
static $MAX_ARRAY_ELEMENTS_PER_REQUEST = 2000;
/**
* Check is linking DIS-allowed
* replacement for get_rd_no_links method, same return value
* php> x i('go-api.name-server', ['socket' => 'localhost:6060'])->fl2mantra([8023690398771773, 407948878760807, 10039069442575594])
* 8023690398771773=1
* 10039069442575594=20
* @return [FL => 1(blocked) | 20(non-mantra)] where linking DIS-allowed
*/
function fl2mantra(array $fls) { #
$fls = array_values($fls);
$z = $this->__xCall("fl2mantra", $fls); // list of answers
$r = [];
foreach ($z as $k => $v) {
if ($v && ($fls[$k]??0))
$r[$fls[$k]] = $v;
}
return $r;
}
/**
* Check if FL is BLOCKED
* php> x i('go-api.name-server', ['socket' => 'localhost:6060'])->fl2blocked([8023690398771773, 407948878760807, 10039069442575594])
* 8023690398771773=1
* @return [FL => 1] where FL blocked
*/
function fl2blocked(array $fls) { #
$fls = array_values($fls);
$z = $this->__xCall("fl2mantra", $fls); // list of answers
$r = [];
foreach ($z as $k => $v) {
if ($v == 1)
$r[$fls[$k]] = $v;
}
return $r;
}
/**
* Wrapper around removals() API call. Allows to process huge amount of hashes in one call.
* @param array $hashes
* @return array
*/
function get_removals(array $hashes): array
{
if (static::$MAX_ARRAY_ELEMENTS_PER_REQUEST < ($array_cnt = count($hashes))) {
// Array is too large. Do multiple requests to service.
$position = 0;
$res[0] = [];
while ($position < $array_cnt) {
$sub_hashes = array_slice($hashes, $position, static::$MAX_ARRAY_ELEMENTS_PER_REQUEST, true);
$sub_res = $this->removals($sub_hashes);
if (!empty($sub_res[0])) {
$res[0] = $sub_res[0] + $res[0];
}
$position = $position + static::$MAX_ARRAY_ELEMENTS_PER_REQUEST;
}
} else {
}
return $res[0] ?? [];
}
// FL popularity
function fl_pop(...$args) {
return $this->_fl_server_call("fl_pop", $args);
}
// Name popularity
function name_pop(...$args) {
return $this->_fl_server_call("name_pop", $args);
}
function fname_comp($prefix) {
return $this->_name_comp($prefix, "first");
}
function lname_comp($prefix) {
return $this->_name_comp($prefix, "last");
}
/**
* FL to { Blocked, T, C, B, G, V }
* @param array $fls
* @return array
* @example i('go-api.name-server')->fl2stats([HB::fl("Mathew Coomer")])
*/
function fl2stats(array $fls) {
$fls = array_values($fls);
$r = $this->__call("fl2stats", $fls); // bTCBGV
$z = [];
$cnt = 0;
foreach ($fls as $k => $fl) {
$v = $r[$k];
if (! is_array($v)) {
\Log::alert("golang/fl2stats-error: ".$v);
}
if ($v[1] == -2)
\Log::alert("golang/fl2stats-data-load-in-progress - wait ~ 20 sec");
$z[$fl] = ["blocked" => $v[0], 't' => $v[1], 'c' => $v[2], 'b' => $v[3], 'g' => $v[4], 'v' => $v[5]];
}
return $z;
}
/**
* Internal - save
* $hits = ['node.attr' => (float|int) value, ...]
*/
function istat_hit(array $hits) {
if (! $hits)
return;
$r = $this->__call("istat_hit", [json_encode($hits)]);
if (! $r) {
if ($cnt = once()) {
\Log::warning("Go-Api IStat_Hit - socket: " . $this->socket_name . " down ; $cnt calls failed");
}
return;
}
$r = $r[0];
if ($r == "OK")
return;
\Log::warning("Go-Api IStat_Hit error: $r");
}
/**
* Internal - save
* $hits = ['node.attr' => (float|int) value, ...]
*/
function istat_sdata(array $data) {
if (! $data)
return;
$r = $this->__call("istat_sdata", [json_encode($data)])[0];
if ($r == "OK")
return;
\Log::warning("Go-Api IStat_HitSData error: $r");
}
/*
1. place prefix first if it is in result set << implement in GO as if prefix is known word - return it
2. fix rare duplicate data case
$tp - first | last
*/
private function _name_comp($prefix, $tp) {
$prefix = trim(strtolower($prefix), " .,");
$PREFIX = ucfirst(strtolower($prefix)); // canonical prefix
$len = strlen($prefix);
if ($len >= 2 && $len < 5 && $prefix[0] != "a" && $prefix[0] == $prefix[1])
return [];
$r = $len < 9 ? $this->socketCall($tp == 'first' ? "fname_comp" : "lname_comp", $prefix) : [];
if (! $r && $len > 5)
$r = DB::all_col("select name from hb_ref.profile_name where tp=? and name like ? order by cnt desc limit 20", $tp, $PREFIX."%");
$r = $r ?? [];
$r = array_unique($r); // minor bugs in teaser4_count (some fnames/lnames got stored as lnames/fnames for otherwise unresolvable names)
// sort by length, then alphabetically
usort($r, function($a, $b) {
if ($l = strlen($a) <=> strlen($b)) return $l;
return $a <=> $b;
});
// if prefix is legal completion - place it first
$pos = array_search($PREFIX, $r);
if ($pos !== false and $pos != 0) {
unset($r[$pos]);
array_unshift($r, $PREFIX);
}
return array_values($r);
}
private function _fl_server_call($method, $args) {
return i("go-api.name-server", ["socket" => $this->C["fl-socket"]])->__call($method, $args);
}
}