-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #62 from kuri-team/release-3.1-05-24-21
Release 3.1 05/24/21
- Loading branch information
Showing
62 changed files
with
2,045 additions
and
1,488 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<?php | ||
|
||
/* | ||
* | ||
* Yabe database browsing interface library. | ||
* MIT License. Copyright (c) 2021 栗 KURI 栗 | ||
* | ||
*/ | ||
|
||
/** | ||
* Retrieve store name and store, then insert them into the store card | ||
* @param $store_name | ||
* @param $store_id | ||
*/ | ||
function display_store($store_name, $store_id) { | ||
$store_href = url_for("/store/store-template/?id={$store_id}"); | ||
echo " | ||
<div class='store-card'> | ||
<a href='$store_href'><img class='store-card-thumbnail' alt='image representation of a shop' src='../../media/image/profile-placeholder_143x143.png'></a> | ||
<a class='store-card-name' href=$store_href>$store_name</a> | ||
</div> | ||
"; | ||
} | ||
|
||
/** | ||
* Retrieve a list of stores and the maximum number of cards that will be display | ||
* Display store cards with a number of cards that is <= the maximum number of cards | ||
* The cards will be ordered ascending based on its position in the list | ||
* @param $stores | ||
* @param $max_cards | ||
*/ | ||
function each_page($stores, $max_cards) { | ||
$min = 0; | ||
$max = $max_cards - $min - 1; | ||
$page = $_GET["page"]; | ||
$list_length = count($stores); | ||
$min += $max_cards * ($page-1); | ||
$max += $max_cards * ($page-1); | ||
if ($max > $list_length) { | ||
$max = $list_length - 1; | ||
} | ||
for ($i = $min; $i <= $max; $i++) { | ||
if (isset($stores[$i])) { | ||
display_store($stores[$i]["store_name"],$stores[$i]["store_id"]); | ||
} | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Use the number of the current page to get the previous page | ||
* @return int | ||
*/ | ||
function prev_page() { | ||
$prev = $_GET["page"] - 1; | ||
// page number cannot be lower than 1 | ||
if ($prev < 1) { | ||
$prev = 1; | ||
} | ||
return $prev; | ||
} | ||
|
||
/** | ||
* Use the number of the current page to get the next page | ||
* @return int | ||
*/ | ||
function next_page($list_length, $max_cards) { | ||
$next = $_GET["page"] + 1; | ||
// calculate the required pages for each browse option | ||
if ($list_length % $max_cards != 0) { | ||
$max_page = floor($list_length / $max_cards) + 1; | ||
} else { | ||
$max_page = $list_length / $max_cards; | ||
} | ||
// page number cannot exceed the maximum number of pages | ||
if ($next > $max_page) { | ||
$next = $max_page; | ||
} | ||
return $next; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
<?php | ||
|
||
require_once(PRIVATE_PATH . "/csv.php"); | ||
|
||
|
||
class Database { | ||
public const CATEGORY_DATABASE = 0; | ||
public const STORE_DATABASE = 1; | ||
public const PRODUCT_DATABASE = 2; | ||
|
||
private static string $category_database_path = PRIVATE_PATH . "/database/categories.csv"; | ||
private static string $store_database_path = PRIVATE_PATH . "/database/stores.csv"; | ||
private static string $product_database_path = PRIVATE_PATH . "/database/products.csv"; | ||
|
||
private int $type; | ||
private array $data = []; | ||
|
||
|
||
public function __construct(int $type) { | ||
$this->type = $type; | ||
switch ($this->type) { | ||
case self::CATEGORY_DATABASE: | ||
$data = read_csv(self::$category_database_path, true); | ||
foreach ($data as $entry) { | ||
$this->data[] = new DatabaseCategory($entry["id"], $entry["name"]); | ||
} | ||
break; | ||
case self::STORE_DATABASE: | ||
$categories = new Database(self::CATEGORY_DATABASE); | ||
$data = read_csv(self::$store_database_path, true); | ||
foreach ($data as $entry) { | ||
$this->data[] = new DatabaseStore( | ||
$entry["id"], | ||
$entry["name"], | ||
$categories->getEntryById($entry["category_id"]), | ||
strtotime($entry["created_time"]), | ||
boolval($entry["featured"]) | ||
); | ||
} | ||
break; | ||
case self::PRODUCT_DATABASE: | ||
$stores = new Database(self::STORE_DATABASE); | ||
$data = read_csv(self::$product_database_path, true); | ||
foreach ($data as $entry) { | ||
$this->data[] = new DatabaseProduct( | ||
$entry["id"], | ||
$entry["name"], | ||
floatval($entry["price"]), | ||
$stores->getEntryById($entry["store_id"]), | ||
strtotime($entry["created_time"]), | ||
boolval($entry["featured_in_mall"]), | ||
boolval($entry["featured_in_store"]) | ||
); | ||
} | ||
break; | ||
} | ||
} | ||
|
||
|
||
public static function merge(Database $database_1, Database $database_2) { | ||
$result = clone $database_1; | ||
$result->setAllEntries(array_merge($result->getAllEntries(), $database_2->getAllEntries())); | ||
return $result; | ||
} | ||
|
||
public function getEntryById(string $id) { | ||
foreach ($this->data as $entry) { | ||
if ($entry->id === $id) { | ||
return $entry; | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
public function getAllEntries(): array { | ||
return $this->data; | ||
} | ||
|
||
private function setAllEntries($data) { | ||
$this->data = $data; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?php | ||
|
||
class DatabaseCategory extends DatabaseEntry { | ||
private static int $count = 0; | ||
|
||
|
||
public function __construct(string $id, string $name) { | ||
parent::__construct($id, $name); | ||
self::$count++; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<?php | ||
|
||
class DatabaseEntry { | ||
public string $id; | ||
public string $name; | ||
public int $search_relevance = 0; | ||
|
||
public function __construct(string $id, string $name) { | ||
$this->id = $id; | ||
$this->name = $name; | ||
} | ||
|
||
|
||
public function isSearchTermMatch(string $search_term, int $levenshtein_match_threshold=0): bool { | ||
$name_elements = preg_split("/[\s,]+/", $this->name); | ||
foreach ($name_elements as $name_element) { | ||
if (levenshtein(strtoupper($name_element), strtoupper($search_term)) <= $levenshtein_match_threshold) { | ||
$this->search_relevance++; | ||
return true; | ||
} | ||
} | ||
$this->search_relevance--; | ||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<?php | ||
|
||
class DatabaseProduct extends DatabaseEntry { | ||
private static int $count = 0; | ||
|
||
public int $price; | ||
public int $created_time; // MUST be an Unix timestamp (number of seconds since the Unix Epoch - January 1 1970 00:00:00 GMT) | ||
public DatabaseStore $store; | ||
public bool $featured_in_mall; | ||
public bool $featured_in_store; | ||
|
||
|
||
public function __construct( | ||
string $id, | ||
string $name, | ||
int $price, | ||
DatabaseStore $store, | ||
int $created_time=null, | ||
bool $featured_in_mall=false, | ||
bool $featured_in_store=false | ||
) { | ||
parent::__construct($id, $name); | ||
$this->price = $price; | ||
if ($created_time === null) { | ||
$this->created_time = time(); | ||
} else { | ||
$this->created_time = $created_time; | ||
} | ||
$this->store = $store; | ||
$this->featured_in_mall = $featured_in_mall; | ||
$this->featured_in_store = $featured_in_store; | ||
|
||
self::$count++; | ||
} | ||
|
||
public function isSearchTermMatch(string $search_term, int $levenshtein_match_threshold=0): bool { | ||
$name_elements = preg_split("/[\s,]+/", $this->name); | ||
foreach ($name_elements as $name_element) { | ||
if (levenshtein(strtoupper($name_element), strtoupper($search_term), 1, 100, 10000) <= $levenshtein_match_threshold) { | ||
$this->search_relevance -= $this->store->search_relevance * 4; | ||
return true; | ||
} | ||
} | ||
$this->search_relevance += $this->store->search_relevance; | ||
return $this->store->isSearchTermMatch($search_term, $levenshtein_match_threshold); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<?php | ||
|
||
class DatabaseStore extends DatabaseEntry { | ||
private static int $count = 0; | ||
|
||
public DatabaseCategory $category; | ||
public int $created_time; // MUST be an Unix timestamp (number of seconds since the Unix Epoch - January 1 1970 00:00:00 GMT) | ||
public bool $featured; // true if this store is featured on mall home, false otherwise TODO: This OOP feature is not yet implemented due to time constraint. Right now it is implemented functionally in /public/mall/index.php | ||
|
||
|
||
public function __construct(string $id, string $name, DatabaseCategory $category, int $created_time=null, bool $featured=false) { | ||
parent::__construct($id, $name); | ||
if ($created_time === null) { | ||
$this->created_time = time(); | ||
} else { | ||
$this->created_time = $created_time; | ||
} | ||
$this->category = $category; | ||
$this->featured = $featured; | ||
|
||
self::$count++; | ||
} | ||
|
||
public function isSearchTermMatch(string $search_term, int $levenshtein_match_threshold=0): bool { | ||
$name_elements = preg_split("/[\s,]+/", $this->name); | ||
foreach ($name_elements as $name_element) { | ||
if (levenshtein(strtoupper($name_element), strtoupper($search_term), 1, 10, 100) <= $levenshtein_match_threshold) { | ||
$this->search_relevance -= $this->category->search_relevance * 2; | ||
return true; | ||
} | ||
} | ||
$this->search_relevance += $this->category->search_relevance; | ||
return $this->category->isSearchTermMatch($search_term, $levenshtein_match_threshold); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
<?php | ||
|
||
class Search { | ||
public const FILTER_ALL = "All"; | ||
public const FILTER_PRODUCTS = "Products"; | ||
public const FILTER_STORES = "Stores"; | ||
|
||
public string $query; | ||
public string $filter; | ||
public array $results = []; | ||
|
||
private array $search_terms = []; | ||
private Database $data; | ||
|
||
|
||
public function __construct(string $query, string $filter=self::FILTER_ALL) { | ||
$this->query = $query; | ||
$search_terms = preg_split("/[\s,]+/", $this->query); | ||
|
||
if ($filter === "Filter") { | ||
$this->filter = self::FILTER_ALL; | ||
} else { | ||
$this->filter = $filter; | ||
} | ||
switch ($this->filter) { | ||
case self::FILTER_ALL: | ||
$this->data = new Database(Database::STORE_DATABASE); | ||
$this->data = Database::merge($this->data, new Database(Database::PRODUCT_DATABASE)); | ||
break; | ||
case self::FILTER_PRODUCTS: | ||
$this->data = new Database(Database::PRODUCT_DATABASE); | ||
break; | ||
case self::FILTER_STORES: | ||
default: | ||
$this->data = new Database(Database::STORE_DATABASE); | ||
break; | ||
} | ||
|
||
foreach ($search_terms as $search_term) { | ||
$this->search_terms[] = new SearchTerm($search_term, $this->data); | ||
} | ||
|
||
$this->generateResults(); | ||
} | ||
|
||
|
||
public function generateResults() { | ||
$match_results = []; | ||
foreach ($this->search_terms as $search_term) { | ||
foreach ($search_term->getAllMatches() as $match) { | ||
if (isset($match_results[$match->id])) { | ||
$match_results[$match->id]++; | ||
} else { | ||
$match_results[$match->id] = 1; | ||
} | ||
} | ||
} | ||
|
||
foreach ($match_results as $match_id => $match_count) { | ||
if ($match_count === count($this->search_terms)) { | ||
if ($this->filter === self::FILTER_ALL || $this->filter === self::FILTER_STORES || $this->filter === self::FILTER_PRODUCTS) { | ||
$this->results[] = $this->data->getEntryById($match_id); | ||
} elseif (levenshtein(explode(" ", $this->data->getEntryById($match_id)->category->name)[0], explode(" ", $this->filter)[2]) < 5) { // TODO: This is a temporary workaround. Replace this with an exact match mechanism. | ||
$this->results[] = $this->data->getEntryById($match_id); | ||
} | ||
} | ||
} | ||
|
||
usort($this->results, function (DatabaseEntry $entry_1, DatabaseEntry $entry_2) { | ||
return $entry_2->search_relevance - $entry_1->search_relevance; | ||
}); | ||
} | ||
} |
Oops, something went wrong.