Smart Conference

Added event room metrics
Now you could query the "metrics" relations on
get event by id endpoint to get
max, min, avg and current values of the room
metrics.

Change-Id: Ic2f695c48a854ab6d4806ef8c471893b7b95d275
This commit is contained in:
Sebastian Marcet 2016-09-09 13:42:15 -03:00
parent a42d0c7e70
commit d483119a20
9 changed files with 596 additions and 33 deletions

View File

@ -48,33 +48,35 @@ final class SerializerRegistry
private function __construct()
{
$this->registry['Summit'] = SummitSerializer::class;
$this->registry['SummitType'] = SummitTypeSerializer::class;
$this->registry['SummitEventType'] = SummitEventTypeSerializer::class;
$this->registry['SummitTicketType'] = SummitTicketTypeSerializer::class;
$this->registry['PresentationCategory'] = PresentationCategorySerializer::class;
$this->registry['PresentationCategoryGroup'] = PresentationCategoryGroupSerializer::class;
$this->registry['Tag'] = TagSerializer::class;
$this->registry['SummitEvent'] = SummitEventSerializer::class;
$this->registry['Presentation'] = PresentationSerializer::class;
$this->registry['PresentationVideo'] = PresentationVideoSerializer::class;
$this->registry['PresentationSlide'] = PresentationSlideSerializer::class;
$this->registry['PresentationLink'] = PresentationLinkSerializer::class;
$this->registry['Company'] = CompanySerializer::class;
$this->registry['PresentationSpeaker'] = PresentationSpeakerSerializer::class;
$this->registry['SummitEventFeedback'] = SummitEventFeedbackSerializer::class;
$this->registry['SummitAttendee'] = SummitAttendeeSerializer::class;
$this->registry['SummitAttendeeSchedule'] = SummitAttendeeScheduleSerializer::class;
$this->registry['SummitEntityEvent'] = SummitEntityEventSerializer::class;
$this->registry['Summit'] = SummitSerializer::class;
$this->registry['SummitType'] = SummitTypeSerializer::class;
$this->registry['SummitEventType'] = SummitEventTypeSerializer::class;
$this->registry['SummitTicketType'] = SummitTicketTypeSerializer::class;
$this->registry['PresentationCategory'] = PresentationCategorySerializer::class;
$this->registry['PresentationCategoryGroup'] = PresentationCategoryGroupSerializer::class;
$this->registry['Tag'] = TagSerializer::class;
$this->registry['SummitEvent'] = SummitEventSerializer::class;
$this->registry['SummitEventMetricsSnapshot'] = SummitEventMetricsSnapshotSerializer::class;
$this->registry['Presentation'] = PresentationSerializer::class;
$this->registry['PresentationVideo'] = PresentationVideoSerializer::class;
$this->registry['PresentationSlide'] = PresentationSlideSerializer::class;
$this->registry['PresentationLink'] = PresentationLinkSerializer::class;
$this->registry['Company'] = CompanySerializer::class;
$this->registry['PresentationSpeaker'] = PresentationSpeakerSerializer::class;
$this->registry['SummitEventFeedback'] = SummitEventFeedbackSerializer::class;
$this->registry['SummitAttendee'] = SummitAttendeeSerializer::class;
$this->registry['SummitAttendeeSchedule'] = SummitAttendeeScheduleSerializer::class;
$this->registry['SummitEntityEvent'] = SummitEntityEventSerializer::class;
// locations
$this->registry['SummitVenue'] = SummitVenueSerializer::class;
$this->registry['SummitVenueRoom'] = SummitVenueRoomSerializer::class;
$this->registry['SummitVenueFloor'] = SummitVenueFloorSerializer::class;
$this->registry['SummitExternalLocation'] = SummitExternalLocationSerializer::class;
$this->registry['SummitHotel'] = SummitHotelSerializer::class;
$this->registry['SummitAirport'] = SummitAirportSerializer::class;
$this->registry['SummitLocationImage'] = SummitLocationImageSerializer::class;
$this->registry['SummitVenue'] = SummitVenueSerializer::class;
$this->registry['SummitVenueRoom'] = SummitVenueRoomSerializer::class;
$this->registry['SummitVenueFloor'] = SummitVenueFloorSerializer::class;
$this->registry['SummitExternalLocation'] = SummitExternalLocationSerializer::class;
$this->registry['SummitHotel'] = SummitHotelSerializer::class;
$this->registry['SummitAirport'] = SummitAirportSerializer::class;
$this->registry['SummitLocationImage'] = SummitLocationImageSerializer::class;
// member
$this->registry['Member'] = MemberSerializer::class;

View File

@ -0,0 +1,32 @@
<?php namespace ModelSerializers;
/**
* Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Libs\ModelSerializers\AbstractSerializer;
/**
* Class SummitEventMetricsSnapshotSerializer
* @package ModelSerializers
*/
final class SummitEventMetricsSnapshotSerializer extends AbstractSerializer
{
protected static $array_mappings = array
(
'Average' => 'avg:json_float',
'Max' => 'max:json_float',
'Min' => 'min:json_float',
'Current' => 'current:json_float',
'TypeName' => 'type:json_string',
'EventId' => 'event_id:json_int',
);
}

View File

@ -12,6 +12,7 @@
* limitations under the License.
**/
use libs\utils\JsonUtils;
use models\summit\SummitEvent;
/**
* Class SummitEventSerializer
@ -70,8 +71,12 @@ class SummitEventSerializer extends SilverStripeSerializer
*/
public function serialize($expand = null, array $fields = array(), array $relations = array(), array $params = array() )
{
if(!count($relations)) $relations = $this->getAllowedRelations();
$event = $this->object;
if(!$event instanceof SummitEvent) return [];
if(!count($relations)) $relations = $this->getAllowedRelations();
$values = parent::serialize($expand, $fields, $relations, $params);
//check if description is empty, if so, set short description
@ -125,6 +130,15 @@ class SummitEventSerializer extends SilverStripeSerializer
}
}
if(in_array('metrics', $relations)){
// show metrics snapshot
$metrics = [];
foreach($event->getMetricsSnapShots() as $snapshot){
$metrics[] = SerializerRegistry::getInstance()->getSerializer($snapshot)->serialize();
}
$values['metrics'] = $metrics;
}
return $values;
}
}

View File

@ -18,6 +18,7 @@ use App\Events\SummitEventUpdated;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use models\exceptions\ValidationException;
use models\main\Company;
use models\main\Tag;
use models\utils\PreRemoveEventArgs;
use models\utils\SilverstripeBaseModel;
@ -705,7 +706,6 @@ class SummitEvent extends SilverstripeBaseModel
$this->pre_update_args = $args;
}
/**
* @ORM\PostUpdate:
*/
@ -722,4 +722,62 @@ class SummitEvent extends SilverstripeBaseModel
Event::fire(new SummitEventCreated($this, $args));
}
public function hasMetricsAvailable(){
if(is_null($this->location)) return false;
if(!$this->location instanceof SummitVenueRoom) return false;
return $this->location->getMetrics()->count() > 0;
}
/**
* @return SummitEventMetricsSnapshot[]
*/
public function getMetricsSnapShots(){
$snapshots = [];
if(is_null($this->location)) return $snapshots;
if(!$this->location instanceof SummitVenueRoom) return $snapshots;
foreach($this->location->getMetrics() as $metric){
$snapshot = $this->getMetricsValuesByType($metric);
if(is_null($snapshot)) continue;
$snapshots[] = $snapshot;
}
return $snapshots;
}
/**
* @param int $type_id
* @return SummitEventMetricsSnapshot
*/
public function getMetricValuesByTypeId($type_id){
$metrics = [];
if(is_null($this->location)) return $metrics;
if(!$this->location instanceof SummitVenueRoom) return $metrics;
$metric_type = $this->location->getMetricsByType($type_id);
if(is_null($metric_type)) return $metrics;
if(!$metric_type instanceof RoomMetricType) return $metrics;
return $this->getMetricsValuesByType($metric_type);
}
/**
* @param RoomMetricType $type
* @return SummitEventMetricsSnapshot
*/
private function getMetricsValuesByType(RoomMetricType $type){
$epoch_start_date = $this->getStartDate()->getTimestamp();
$epoch_end_date = $this->getEndDate()->getTimestamp();
return new SummitEventMetricsSnapshot
(
$this,
$type,
$type->getMeanValueByTimeWindow($epoch_start_date, $epoch_end_date),
$type->getMaxValueByTimeWindow($epoch_start_date, $epoch_end_date),
$type->getMinValueByTimeWindow($epoch_start_date, $epoch_end_date),
$type->getCurrentValueByTimeWindow($epoch_start_date, $epoch_end_date)
);
}
}

View File

@ -0,0 +1,95 @@
<?php namespace models\summit;
/**
* Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Doctrine\ORM\Mapping AS ORM;
use models\utils\SilverstripeBaseModel;
/**
* @ORM\Entity
* @ORM\Table(name="RoomMetricSampleData")
* Class RoomMetricSampleData
* @package RoomMetricType\summit
*/
final class RoomMetricSampleData extends SilverstripeBaseModel
{
/**
* @ORM\Column(name="TimeStamp", type="integer")
* @var int
*/
private $timestamp;
/**
* @ORM\Column(name="Value", type="float")
* @var float
*/
private $value;
/**
* @ORM\ManyToOne(targetEntity="models\summit\RoomMetricType", inversedBy="samples")
* @ORM\JoinColumn(name="TypeID", referencedColumnName="ID")
* @var RoomMetricType
*/
private $type;
/**
* @return int
*/
public function getTimestamp()
{
return $this->timestamp;
}
/**
* @param int $timestamp
*/
public function setTimestamp($timestamp)
{
$this->timestamp = $timestamp;
}
/**
* @return float
*/
public function getValue()
{
return $this->value;
}
/**
* @param float $value
*/
public function setValue($value)
{
$this->value = $value;
}
/**
* @return RoomMetricType
*/
public function getType()
{
return $this->type;
}
/**
* @param RoomMetricType $type
*/
public function setType($type)
{
$this->type = $type;
}
}

View File

@ -0,0 +1,200 @@
<?php namespace models\summit;
/**
* Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping AS ORM;
use models\utils\SilverstripeBaseModel;
/**
* @ORM\Entity
* @ORM\Table(name="RoomMetricType")
* Class SummitVenueRoom
* @package RoomMetricType\summit
*/
class RoomMetricType extends SilverstripeBaseModel
{
/**
* @ORM\Column(name="Type", type="string")
* @var string
*/
private $type;
/**
* @ORM\Column(name="Endpoint", type="string")
* @var string
*/
private $endpoint;
/**
* @ORM\ManyToOne(targetEntity="models\summit\SummitVenueRoom", inversedBy="metrics")
* @ORM\JoinColumn(name="RoomID", referencedColumnName="ID")
* @var SummitVenueRoom
*/
private $room;
/**
* @ORM\OneToMany(targetEntity="RoomMetricSampleData", mappedBy="type", cascade={"persist"})
*/
private $samples;
/**
* RoomMetricType constructor.
*/
public function __construct()
{
$this->samples = new ArrayCollection();
}
/**
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* @param string $type
*/
public function setType($type)
{
$this->type = $type;
}
/**
* @return string
*/
public function getEndpoint()
{
return $this->endpoint;
}
/**
* @param string $endpoint
*/
public function setEndpoint($endpoint)
{
$this->endpoint = $endpoint;
}
/**
* @return SummitVenueRoom
*/
public function getRoom()
{
return $this->room;
}
/**
* @param SummitVenueRoom $room
*/
public function setRoom($room)
{
$this->room = $room;
}
/**
* @return ArrayCollection
*/
public function getSamples()
{
return $this->samples;
}
/**
* @param ArrayCollection $samples
*/
public function setSamples($samples)
{
$this->samples = $samples;
}
/**
* @param int $epoch_start_date
* @param int $epoch_end_date
* @return float
*/
public function getMaxValueByTimeWindow($epoch_start_date, $epoch_end_date){
$samples = $this->getValuesByTimeWindow($epoch_start_date, $epoch_end_date, 'value', Criteria::DESC);
$max = count($samples) > 0 ? $samples[0] : null;
return !is_null($max) ? $max->getValue() : 0.0;
}
/**
* @param int $epoch_start_date
* @param int $epoch_end_date
* @return float
*/
public function getMinValueByTimeWindow($epoch_start_date, $epoch_end_date){
$samples = $this->getValuesByTimeWindow($epoch_start_date, $epoch_end_date, 'value', Criteria::ASC);
$min = count($samples) > 0 ? $samples[0] : null;
return !is_null($min) ? $min->getValue() : 0.0;
}
/**
* @param int $epoch_start_date
* @param int $epoch_end_date
* @return float
*/
public function getCurrentValueByTimeWindow($epoch_start_date, $epoch_end_date){
$utc_epoch = time();
$rounded_epoch = $utc_epoch- $utc_epoch % 60;
$res = 0.0;
if($epoch_start_date <= $rounded_epoch && $rounded_epoch <= $epoch_end_date){
$samples = $this->getValuesByTimeWindow($epoch_start_date, $epoch_end_date, 'timestamp', Criteria::ASC);
foreach($samples as $sample){
if($sample->getTimestamp() == $rounded_epoch)
$res = $sample->getValue();
}
}
return $res;
}
/**
* @param int $epoch_start_date
* @param int $epoch_end_date
* @return float
*/
public function getMeanValueByTimeWindow($epoch_start_date, $epoch_end_date){
$samples = $this->getValuesByTimeWindow($epoch_start_date, $epoch_end_date, 'value', Criteria::ASC);
$sum = 0.0;
foreach($samples as $sample){
$sum += $sample->getValue();
}
return count($samples) > 0 ? $sum / count($samples) : 0.0;
}
/**
* @param int $epoch_start_date
* @param int $epoch_end_date
* @param string|null $order_by
* @param string|null $order_by_direction
* @return array
*/
public function getValuesByTimeWindow($epoch_start_date, $epoch_end_date, $order_by = null, $order_by_direction = null){
$criteria = Criteria::create()
->where(Criteria::expr()->gte("timestamp", $epoch_start_date))
->andWhere(Criteria::expr()->lte("timestamp", $epoch_end_date));
if(!is_null($order_by) && !is_null($order_by_direction)){
$criteria = $criteria->orderBy(array($order_by => $order_by_direction));
}
$samples = $this->samples->matching($criteria);
return $samples->toArray();
}
}

View File

@ -0,0 +1,123 @@
<?php namespace models\summit;
/**
* Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
/**
* Class SummitEventMetricsSnapshot
* @package models\summit
*/
final class SummitEventMetricsSnapshot
{
/**
* @var float
*/
private $average;
/**
* @var float
*/
private $max;
/**
* @var float
*/
private $min;
/**
* @var float
*/
private $current;
/**
* @var RoomMetricType
*/
private $type;
/**
* @var SummitEvent
*/
private $event;
/**
* SummitEventMetricsSnapshot constructor.
* @param SummitEvent $event
* @param RoomMetricType $type
* @param $average
* @param $max
* @param $min
* @param $current
*/
public function __construct(SummitEvent $event, RoomMetricType $type, $average, $max, $min, $current)
{
$this->average = $average;
$this->max = $max;
$this->min = $min;
$this->current = $current;
$this->event = $event;
$this->type = $type;
}
/**
* @return RoomMetricType
*/
public function getType()
{
return $this->type;
}
/**
* @return string
*/
public function getTypeName()
{
return $this->type->getType();
}
/**
* @return int
*/
public function getEventId(){
return $this->event->getId();
}
/**
* @return float
*/
public function getAverage()
{
return $this->average;
}
/**
* @return float
*/
public function getMax()
{
return $this->max;
}
/**
* @return float
*/
public function getMin()
{
return $this->min;
}
/**
* @return float
*/
public function getCurrent()
{
return $this->current;
}
}

View File

@ -13,6 +13,8 @@
* limitations under the License.
**/
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping AS ORM;
/**
@ -140,4 +142,43 @@ class SummitVenueRoom extends SummitAbstractLocation
* @var bool
*/
private $override_blackouts;
/**
* @ORM\OneToMany(targetEntity="RoomMetricType", mappedBy="room", cascade={"persist"})
*/
private $metrics;
/**
* @return ArrayCollection
*/
public function getMetrics()
{
return $this->metrics;
}
/**
* @param ArrayCollection $metrics
*/
public function setMetrics($metrics)
{
$this->metrics = $metrics;
}
/**
* SummitVenueRoom constructor.
*/
public function __construct()
{
$this->metrics = new ArrayCollection();
}
/**
* @param int $type_id
* @return RoomMetricType
*/
public function getMetricByType($type_id){
$criteria = Criteria::create()->where(Criteria::expr()->eq("id", $type_id));
return $this->metrics->matching($criteria)->first();
}
}

View File

@ -717,13 +717,12 @@ final class OAuth2SummitApiTest extends ProtectedApiTest
public function testGetPublishedEventFields(){
$params = array
(
'id' => 6,
'event_id' => 8900,
'fields' => 'id,avg_feedback_rate,head_count',
'relations' => 'none'
'id' => 7,
'event_id' => 15987,
'fields' => 'id, avg_feedback_rate, head_count',
'relations' => 'metrics'
);
$headers = array
@ -732,7 +731,6 @@ final class OAuth2SummitApiTest extends ProtectedApiTest
"CONTENT_TYPE" => "application/json"
);
$response = $this->action
(
"GET",