Compare commits
9 commits
master
...
764-aggreg
| Author | SHA1 | Date | |
|---|---|---|---|
| 60ca4cf269 | |||
|
|
244f93ddc9 | ||
|
|
a248731851 | ||
|
|
25d7c30f73 | ||
|
|
cf34519385 | ||
|
|
a3c875b907 | ||
|
|
629829691c | ||
|
|
83c0e1cd51 | ||
|
|
53a45ac4f4 |
5 changed files with 332 additions and 10 deletions
123
src/Command/LoadAggregateRiderRatingsComand.php
Normal file
123
src/Command/LoadAggregateRiderRatingsComand.php
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Command;
|
||||||
|
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
use App\Entity\AggregatedRiderRating;
|
||||||
|
|
||||||
|
use PDO;
|
||||||
|
|
||||||
|
class LoadAggregateRiderRatingsComand extends Command
|
||||||
|
{
|
||||||
|
protected $em;
|
||||||
|
|
||||||
|
public function __construct(EntityManagerInterface $em)
|
||||||
|
{
|
||||||
|
$this->em = $em;
|
||||||
|
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName('aggregated_rider_rating:load')
|
||||||
|
->setDescription('Add rider ratings to aggregated rider rating.')
|
||||||
|
->setHelp('Add rider ratings to aggregated rider rating.');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
// get the ids of all riders
|
||||||
|
$rider_id_list = $this->getRiderIds();
|
||||||
|
|
||||||
|
$this->processAggregateRiderRating($rider_id_list);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processAggregateRiderRating($rider_id_list)
|
||||||
|
{
|
||||||
|
$db = $this->em->getConnection();
|
||||||
|
|
||||||
|
$agg_rider_ratings = [];
|
||||||
|
|
||||||
|
// get all rider ratings per rider
|
||||||
|
$rr_query_sql = 'SELECT rating FROM rider_rating WHERE rider_id = :id';
|
||||||
|
$rr_query_stmt = $db->prepare($rr_query_sql);
|
||||||
|
foreach ($rider_id_list as $key => $rider_id)
|
||||||
|
{
|
||||||
|
$rr_query_stmt->bindValue('id', $rider_id);
|
||||||
|
$results = $rr_query_stmt->executeQuery();
|
||||||
|
|
||||||
|
$total_jos = 0;
|
||||||
|
$total_rating = 0;
|
||||||
|
while ($row = $results->fetchAssociative())
|
||||||
|
{
|
||||||
|
$rating = $row['rating'];
|
||||||
|
|
||||||
|
$total_rating = bcadd($total_rating, $rating, 2);
|
||||||
|
|
||||||
|
// increment number of JOs per rider
|
||||||
|
$total_jos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute average
|
||||||
|
$agg_rating = 0;
|
||||||
|
if ($total_jos > 0)
|
||||||
|
$agg_rating = bcdiv($total_rating, $total_jos, 2);
|
||||||
|
|
||||||
|
$agg_rider_ratings[$rider_id] = [
|
||||||
|
'agg_rating' => $agg_rating,
|
||||||
|
'agg_count' => $total_jos,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// create aggregated rider rating
|
||||||
|
$this->createAggregatedRiderRating($agg_rider_ratings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function createAggregatedRiderRating($agg_rider_ratings)
|
||||||
|
{
|
||||||
|
// error_log(print_r($agg_rider_ratings, true));
|
||||||
|
|
||||||
|
foreach ($agg_rider_ratings as $key => $data)
|
||||||
|
{
|
||||||
|
// create new AggregatedRiderRating object
|
||||||
|
$obj = new AggregatedRiderRating();
|
||||||
|
|
||||||
|
// set fields
|
||||||
|
$obj->setRiderId($key)
|
||||||
|
->setAggregateRating($data['agg_rating'])
|
||||||
|
->setAggregateCount($data['agg_count']);
|
||||||
|
|
||||||
|
// save to database
|
||||||
|
$this->em->persist($obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->em->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getRiderIds()
|
||||||
|
{
|
||||||
|
$rider_ids = [];
|
||||||
|
$db = $this->em->getConnection();
|
||||||
|
|
||||||
|
$query_sql = 'SELECT id FROM rider';
|
||||||
|
$query_stmt = $db->prepare($query_sql);
|
||||||
|
$results = $query_stmt->executeQuery();
|
||||||
|
|
||||||
|
while ($row = $results->fetchAssociative())
|
||||||
|
{
|
||||||
|
$rider_ids[] = $row['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rider_ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -71,6 +71,7 @@ use App\Entity\Hub;
|
||||||
use App\Entity\SAPBattery;
|
use App\Entity\SAPBattery;
|
||||||
use App\Entity\WarrantySerial;
|
use App\Entity\WarrantySerial;
|
||||||
use App\Entity\CustomerMetadata;
|
use App\Entity\CustomerMetadata;
|
||||||
|
use App\Entity\AggregatedRiderRating;
|
||||||
|
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use DateInterval;
|
use DateInterval;
|
||||||
|
|
@ -1715,7 +1716,13 @@ class APIController extends Controller implements LoggedController
|
||||||
$em->persist($rating);
|
$em->persist($rating);
|
||||||
$em->flush();
|
$em->flush();
|
||||||
|
|
||||||
// TODO: set average rating in rider entity
|
// need to update or add aggregated rider rating
|
||||||
|
$average_rating = $this->updateAggregatedRiderRating($em, $rider, $rating_num);
|
||||||
|
|
||||||
|
// TODO: preliminary rating computation on the entity for now
|
||||||
|
$rider->updateRatingAverage($average_rating);
|
||||||
|
$em->persist($rider);
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
$res->setData([]);
|
$res->setData([]);
|
||||||
|
|
||||||
|
|
@ -4849,6 +4856,60 @@ class APIController extends Controller implements LoggedController
|
||||||
return $jo_data;
|
return $jo_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function updateAggregatedRiderRating($em, $rider, $rating_num)
|
||||||
|
{
|
||||||
|
$rider_id = $rider->getID();
|
||||||
|
$agg_rating = 0;
|
||||||
|
|
||||||
|
// check if rider is in the the aggregated rider rating table
|
||||||
|
$agg_rider_rating = $em->getRepository(AggregatedRiderRating::class)->findOneBy(['rider_id' => $rider_id]);
|
||||||
|
if ($agg_rider_rating == null)
|
||||||
|
{
|
||||||
|
// new rider, new entry
|
||||||
|
$old_rating = 0;
|
||||||
|
$old_count = 0;
|
||||||
|
$new_count = 1;
|
||||||
|
$agg_rating = $this->computeAggregatedRiderRating($old_rating, $rating_num, $old_count, $new_count);
|
||||||
|
|
||||||
|
$obj = new AggregatedRiderRating();
|
||||||
|
$obj->setRiderId($rider_id)
|
||||||
|
->setAggregateRating($agg_rating)
|
||||||
|
->setAggregateCount($new_count);
|
||||||
|
|
||||||
|
$em->persist($obj);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// existing rider, update entry
|
||||||
|
$r_rating = $agg_rider_rating->getAggregateRating();
|
||||||
|
$r_count = $agg_rider_rating->getAggregateCount();
|
||||||
|
|
||||||
|
$new_count = $r_count + 1;
|
||||||
|
|
||||||
|
$agg_rating = $this->computeAggregatedRiderRating($r_rating, $rating_num, $r_count, $new_count);
|
||||||
|
|
||||||
|
// set updated values for entry
|
||||||
|
$agg_rider_rating->setAggregateRating($agg_rating)
|
||||||
|
->setAggregateCount($new_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
return $agg_rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function computeAggregatedRiderRating($old_rating, $new_rating, $r_count, $new_count)
|
||||||
|
{
|
||||||
|
// ((existing aggregate rating * existing aggregate count) + new rating) / new count
|
||||||
|
$agg_comp = bcmul($old_rating, $r_count, 2);
|
||||||
|
|
||||||
|
$rating = bcadd($agg_comp, $new_rating, 2);
|
||||||
|
|
||||||
|
$agg_rating = bcdiv($rating, $new_count, 2);
|
||||||
|
|
||||||
|
return $agg_rating;
|
||||||
|
}
|
||||||
|
|
||||||
protected function normalizeString($string)
|
protected function normalizeString($string)
|
||||||
{
|
{
|
||||||
return trim(strtolower($string));
|
return trim(strtolower($string));
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ use App\Ramcar\JOStatus;
|
||||||
use App\Ramcar\APIRiderStatus;
|
use App\Ramcar\APIRiderStatus;
|
||||||
use App\Entity\RiderRating;
|
use App\Entity\RiderRating;
|
||||||
use App\Entity\JobOrder;
|
use App\Entity\JobOrder;
|
||||||
|
use App\Entity\AggregatedRiderRating;
|
||||||
use App\Service\RiderTracker;
|
use App\Service\RiderTracker;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
@ -230,12 +231,69 @@ class RiderController extends ApiController
|
||||||
$this->em->persist($rating);
|
$this->em->persist($rating);
|
||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
|
|
||||||
|
// need to update or add aggregated rider rating
|
||||||
|
$average_rating = $this->updateAggregatedRiderRating($rider, $rating_num);
|
||||||
|
|
||||||
// TODO: preliminary rating computation on the entity for now
|
// TODO: preliminary rating computation on the entity for now
|
||||||
$rider->updateRatingAverage();
|
$rider->updateRatingAverage($average_rating);
|
||||||
$this->em->persist($rider);
|
$this->em->persist($rider);
|
||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
|
|
||||||
// response
|
// response
|
||||||
return new ApiResponse();
|
return new ApiResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function updateAggregatedRiderRating($rider, $rating_num)
|
||||||
|
{
|
||||||
|
$rider_id = $rider->getID();
|
||||||
|
$agg_rating = 0;
|
||||||
|
|
||||||
|
// check if rider is in the the aggregated rider rating table
|
||||||
|
$agg_rider_rating = $this->em->getRepository(AggregatedRiderRating::class)->findOneBy(['rider_id' => $rider_id]);
|
||||||
|
if ($agg_rider_rating == null)
|
||||||
|
{
|
||||||
|
// new rider, new entry
|
||||||
|
$old_rating = 0;
|
||||||
|
$old_count = 0;
|
||||||
|
$new_count = 1;
|
||||||
|
$agg_rating = $this->computeAggregatedRiderRating($old_rating, $rating_num, $old_count, $new_count);
|
||||||
|
|
||||||
|
$obj = new AggregatedRiderRating();
|
||||||
|
$obj->setRiderId($rider_id)
|
||||||
|
->setAggregateRating($agg_rating)
|
||||||
|
->setAggregateCount($new_count);
|
||||||
|
|
||||||
|
$this->em->persist($obj);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// existing rider, update entry
|
||||||
|
$r_rating = $agg_rider_rating->getAggregateRating();
|
||||||
|
$r_count = $agg_rider_rating->getAggregateCount();
|
||||||
|
|
||||||
|
$new_count = $r_count + 1;
|
||||||
|
|
||||||
|
$agg_rating = $this->computeAggregatedRiderRating($r_rating, $rating_num, $r_count, $new_count);
|
||||||
|
|
||||||
|
// set updated values for entry
|
||||||
|
$agg_rider_rating->setAggregateRating($agg_rating)
|
||||||
|
->setAggregateCount($new_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->em->flush();
|
||||||
|
|
||||||
|
return $agg_rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function computeAggregatedRiderRating($old_rating, $new_rating, $r_count, $new_count)
|
||||||
|
{
|
||||||
|
// ((existing aggregate rating * existing aggregate count) + new rating) / new count
|
||||||
|
$agg_comp = bcmul($old_rating, $r_count, 2);
|
||||||
|
|
||||||
|
$rating = bcadd($agg_comp, $new_rating, 2);
|
||||||
|
|
||||||
|
$agg_rating = bcdiv($rating, $new_count, 2);
|
||||||
|
|
||||||
|
return $agg_rating;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
86
src/Entity/AggregatedRiderRating.php
Normal file
86
src/Entity/AggregatedRiderRating.php
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Entity
|
||||||
|
* @ORM\Table(name="aggregated_rider_rating", indexes={
|
||||||
|
* @ORM\Index(name="rider_id_idx", columns={"rider_id"}),
|
||||||
|
* })
|
||||||
|
*/
|
||||||
|
class AggregatedRiderRating
|
||||||
|
{
|
||||||
|
// unique id
|
||||||
|
/**
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\Column(type="integer")
|
||||||
|
* @ORM\GeneratedValue(strategy="AUTO")
|
||||||
|
*/
|
||||||
|
protected $id;
|
||||||
|
|
||||||
|
// rider id, loose association
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="integer", nullable=true)
|
||||||
|
*/
|
||||||
|
protected $rider_id;
|
||||||
|
|
||||||
|
// average rating of rider
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="float")
|
||||||
|
*/
|
||||||
|
protected $aggregate_rating;
|
||||||
|
|
||||||
|
// number of job orders
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="integer")
|
||||||
|
*/
|
||||||
|
protected $aggregate_count;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->aggregate_rating = 0;
|
||||||
|
$this->aggregate_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getID()
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRiderId($rider_id)
|
||||||
|
{
|
||||||
|
$this->rider_id = $rider_id;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRiderId()
|
||||||
|
{
|
||||||
|
return $this->rider_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAggregateRating($aggregate_rating)
|
||||||
|
{
|
||||||
|
$this->aggregate_rating = $aggregate_rating;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAggregateRating()
|
||||||
|
{
|
||||||
|
return $this->aggregate_rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAggregateCount($aggregate_count)
|
||||||
|
{
|
||||||
|
$this->aggregate_count = $aggregate_count;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAggregateCount()
|
||||||
|
{
|
||||||
|
return $this->aggregate_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -241,15 +241,9 @@ class Rider
|
||||||
return $this->image_file;
|
return $this->image_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateRatingAverage()
|
public function updateRatingAverage($rating)
|
||||||
{
|
{
|
||||||
$total = 0;
|
$this->setCurrentRating($rating);
|
||||||
|
|
||||||
foreach ($this->ratings as $rating) {
|
|
||||||
$total += $rating->getRating();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->setCurrentRating(round($total / $this->ratings->count(), 2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setCurrentRating($rating)
|
public function setCurrentRating($rating)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue