From dbf019135a515c4066c49a6740d4f9f9441ebdf7 Mon Sep 17 00:00:00 2001 From: James Cole Date: Wed, 25 Jul 2018 06:18:20 +0200 Subject: [PATCH] Simplified tag cloud. --- app/Repositories/Tag/TagRepository.php | 172 +++++++++++++++---------- 1 file changed, 107 insertions(+), 65 deletions(-) diff --git a/app/Repositories/Tag/TagRepository.php b/app/Repositories/Tag/TagRepository.php index 4317a5b907..715ca44e13 100644 --- a/app/Repositories/Tag/TagRepository.php +++ b/app/Repositories/Tag/TagRepository.php @@ -286,82 +286,41 @@ class TagRepository implements TagRepositoryInterface public function tagCloud(?int $year): array { // Some vars - $min = null; - $max = '0'; $return = []; - // get all tags in the year (if present): - $tagQuery = $this->user->tags() - ->leftJoin('tag_transaction_journal', 'tag_transaction_journal.tag_id', '=', 'tags.id') - ->leftJoin('transaction_journals', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') - ->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->where( - function (Builder $query) { - $query->where('transactions.amount', '>', 0); - $query->orWhereNull('transactions.amount'); - } - ) - ->groupBy(['tags.id', 'tags.tag']); + $tags = $this->getTagsInYear($year); + $max = $this->getMaxAmount($tags); + $min = $this->getMinAmount($tags); + $diff = bcsub($max, $min); + $return = []; + Log::debug(sprintf('Minimum is %s, maximum is %s, difference is %s', $min, $max, $diff)); - // add date range (or not): - if (null === $year) { - Log::debug('Get tags without a date.'); - $tagQuery->whereNull('tags.date'); - } - if (null !== $year) { - Log::debug(sprintf('Get tags with year %s.', $year)); - $tagQuery->where('tags.date', '>=', $year . '-01-01 00:00:00')->where('tags.date', '<=', $year . '-12-31 23:59:59'); + // default scale is from 12 to 24, so 12 points. + $minimumFont = '12'; + $maxPoints = '12'; + $pointsPerCoin = '0'; + + // for each full coin in tag, add so many points: + if (0 !== bccomp($diff, '0')) { + $pointsPerCoin = bcdiv($maxPoints, $diff); } - $result = $tagQuery->get(['tags.id', 'tags.tag', DB::raw('SUM(transactions.amount) as amount_sum')]); + + Log::debug(sprintf('Each coin in a tag earns it %s points', $pointsPerCoin)); /** @var Tag $tag */ - foreach ($result as $tag) { - $tagsWithAmounts[$tag->id] = (string)$tag->amount_sum; - $amount = '' !== $tagsWithAmounts[$tag->id] ? $tagsWithAmounts[$tag->id] : '0'; - if (null === $min) { - $min = $amount; - } - $max = 1 === bccomp($amount, $max) ? $amount : $max; - $min = -1 === bccomp($amount, $min) ? $amount : $min; - - $temporary[] = [ - 'amount' => $amount, - 'tag' => [ - 'id' => $tag->id, - 'tag' => $tag->tag, - ], - ]; - Log::debug(sprintf('After tag "%s", max is %s and min is %s.', $tag->tag, $max, $min)); - } - $min = $min ?? '0'; - Log::debug(sprintf('FINAL max is %s, FINAL min is %s', $max, $min)); - // the difference between max and min: - $range = bcsub($max, $min); - Log::debug(sprintf('The range is: %s', $range)); - - // each euro difference is this step in the scale: - $step = 0.0 !== (float)$range ? 8 / (float)$range : 0; - Log::debug(sprintf('The step is: %f', $step)); - $size = 12; - - foreach ($result as $tag) { - if (0 === $step) { - // easy: size is 12: - $size = 12; - } - if (0 !== $step) { - $amount = bcsub((string)$tag->amount_sum, $min); - Log::debug(sprintf('Work with amount %s for tag %s', $amount, $tag->tag)); - $size = ((int)(float)$amount * $step) + 12; - } + foreach ($tags as $tag) { + $amount = (string)$tag->amount_sum; + $amount = '' === $amount ? '0' : $amount; + $pointsForTag = bcmul($amount, $pointsPerCoin); + $fontSize = bcadd($minimumFont, $pointsForTag); + Log::debug(sprintf('Tag "%s": Amount is %s, so points is %s', $tag->tag, $amount, $fontSize)); + // return value for tag cloud: $return[$tag->id] = [ - 'size' => $size, + 'size' => $fontSize, 'tag' => $tag->tag, 'id' => $tag->id, ]; - - Log::debug(sprintf('Size is %d', $size)); } return $return; @@ -385,4 +344,87 @@ class TagRepository implements TagRepositoryInterface return $tag; } + + /** + * @param Collection $tags + * + * @return string + */ + private function getMaxAmount(Collection $tags): string + { + $max = '0'; + /** @var Tag $tag */ + foreach ($tags as $tag) { + $amount = (string)$tag->amount_sum; + $amount = '' === $amount ? '0' : $amount; + $max = 1 === bccomp($amount, $max) ? $amount : $max; + + } + Log::debug(sprintf('Maximum is %s.', $max)); + + return $max; + } + + /** + * @param Collection $tags + * + * @return string + */ + private function getMinAmount(Collection $tags): string + { + $min = null; + + /** @var Tag $tag */ + foreach ($tags as $tag) { + $amount = (string)$tag->amount_sum; + $amount = '' === $amount ? '0' : $amount; + + if (null === $min) { + $min = $amount; + } + $min = -1 === bccomp($amount, $min) ? $amount : $min; + } + + + if (null === $min) { + $min = '0'; + } + Log::debug(sprintf('Minimum is %s.', $min)); + + return $min; + } + + /** + * @param int|null $year + * + * @return Collection + */ + private function getTagsInYear(?int $year): Collection + { + // get all tags in the year (if present): + $tagQuery = $this->user->tags() + ->leftJoin('tag_transaction_journal', 'tag_transaction_journal.tag_id', '=', 'tags.id') + ->leftJoin('transaction_journals', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') + ->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') + ->where( + function (Builder $query) { + $query->where('transactions.amount', '>', 0); + $query->orWhereNull('transactions.amount'); + } + ) + ->groupBy(['tags.id', 'tags.tag']); + + // add date range (or not): + if (null === $year) { + Log::debug('Get tags without a date.'); + $tagQuery->whereNull('tags.date'); + } + if (null !== $year) { + Log::debug(sprintf('Get tags with year %s.', $year)); + $tagQuery->where('tags.date', '>=', $year . '-01-01 00:00:00')->where('tags.date', '<=', $year . '-12-31 23:59:59'); + } + + return $tagQuery->get(['tags.id', 'tags.tag', DB::raw('SUM(transactions.amount) as amount_sum')]); + + } }