Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 182
0.00% covered (danger)
0.00%
0 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
StatisticsService
0.00% covered (danger)
0.00%
0 / 182
0.00% covered (danger)
0.00%
0 / 13
3906
0.00% covered (danger)
0.00%
0 / 1
 getDateFromNow
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
42
 getDateFromNowInMonthYear
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getWagePerHour
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 1
210
 getCompanyWagePerHour
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
42
 getCostSaved
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getWordsPerMinute
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
72
 getCompanyDefaultSetting
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
2
 getTimeSaved
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getOldTimeSaved
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 getOldCharactersTyped
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 getOldChart
0.00% covered (danger)
0.00%
0 / 44
0.00% covered (danger)
0.00%
0 / 1
110
 transformHubSpotRecord
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
20
 transformHubSpotRecordToRawChartData
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2
3namespace App\Http\Services;
4
5use Carbon\Carbon;
6use App\Http\Models\Auth\User;
7use App\Http\Models\FlyCutUsage;
8use App\Http\Models\Setting;
9use Illuminate\Support\Facades\DB;
10use App\Http\Models\ShortcutWithUsage;
11
12class StatisticsService
13{
14    /**
15     * Get the date whose difference from now is specified in the params.
16     *
17     * @param  string  $type month|day|hour
18     */
19    public function getDateFromNow(?int $differenceFromNow = 12, ?string $type = 'month'): Carbon
20    {
21        $from = now()->subMonths(12);
22
23        if (empty($differenceFromNow)) {
24            return $from;
25        }
26
27        switch ($type) {
28            case 'month':
29                $from = now()->subMonths($differenceFromNow);
30                break;
31            case 'day':
32                $from = now()->subDays($differenceFromNow);
33                break;
34            case 'hour':
35                $from = now()->subHours($differenceFromNow);
36                break;
37            default:
38                $from = now()->subMonths(12);
39                break;
40        }
41
42        return $from;
43    }
44
45    /**
46     * Get the date in month year format whose difference from now is specified in the params.
47     *
48     * @param  string  $type month|day|hour
49     */
50    public function getDateFromNowInMonthYear(?int $differenceFromNow = 12, ?string $type = 'month'): string
51    {
52        return $this->getDateFromNow($differenceFromNow, $type)->format('M Y');
53    }
54
55    public function getWagePerHour(User $user, Carbon $date): float
56    {
57        $wagePerHour = FlyCutUsage::WAGE_PER_HOUR;
58
59        if (filled($user->setting)) {
60            $wagePerHourHistory = $user->setting->wage_per_hour_history ?? [];
61
62            $historyWagePerHour = null;
63            if (count($wagePerHourHistory) > 0) {
64                $wagePerHourHistory = array_filter($wagePerHourHistory, function ($item) use ($date) {
65                    return Carbon::parse($item['date'])->lte($date);
66                });
67
68                if (count($wagePerHourHistory) > 0) {
69                    $historyWagePerHour = end($wagePerHourHistory)['wage_per_hour'];
70                }
71            }
72
73            if ($historyWagePerHour) {
74                $wagePerHour = $historyWagePerHour;
75            } elseif (!empty($user->setting->wage_per_hour)) {
76                $wagePerHour = $user->setting->wage_per_hour;
77            }
78        }
79
80        if (!empty($user->company_id) && strtolower($user->status) == 'active') {
81            $companySetting = Setting::where('company_id', $user->company_id)->first();
82            if ($companySetting && $companySetting->override_user_wage_per_hour) {
83                $wagePerHourHistory = $companySetting->wage_per_hour_history ?? [];
84
85                $historyWagePerHour = null;
86                if (count($wagePerHourHistory) > 0) {
87                    $wagePerHourHistory = array_filter($wagePerHourHistory, function ($item) use ($date) {
88                        return Carbon::parse($item['date'])->lte($date);
89                    });
90
91                    if (count($wagePerHourHistory) > 0) {
92                        $historyWagePerHour = end($wagePerHourHistory)['wage_per_hour'];
93                    }
94                }
95
96                if ($historyWagePerHour) {
97                    $wagePerHour = $historyWagePerHour;
98                } elseif (!empty($companySetting->wage_per_hour)) {
99                    $wagePerHour = $companySetting->wage_per_hour;
100                }
101            }
102        }
103
104        return $wagePerHour;
105    }
106
107    public function getCompanyWagePerHour(string $companyId, Carbon $date): float
108    {
109        $wagePerHour = FlyCutUsage::WAGE_PER_HOUR;
110
111        $setting = Setting::where('company_id', $companyId)->first();
112
113        if (filled($setting)) {
114            $wagePerHourHistory = $setting->wage_per_hour_history ?? [];
115
116            $historyWagePerHour = null;
117            if (count($wagePerHourHistory) > 0) {
118                $wagePerHourHistory = array_filter($wagePerHourHistory, function ($item) use ($date) {
119                    return Carbon::parse($item['date'])->lte($date);
120                });
121
122                if (count($wagePerHourHistory) > 0) {
123                    $historyWagePerHour = end($wagePerHourHistory)['wage_per_hour'];
124                }
125            }
126
127            if ($historyWagePerHour) {
128                $wagePerHour = $historyWagePerHour;
129            } elseif (!empty($setting->wage_per_hour)) {
130                $wagePerHour = $setting->wage_per_hour;
131            }
132        }
133
134        return $wagePerHour;
135    }
136
137    /**
138     * Get the time saved in hours.
139     */
140    public function getCostSaved(User $user, float $timeSaved, Carbon $date): float
141    {
142        $wagePerHour = $this->getWagePerHour($user, $date);
143
144        return round($timeSaved * $wagePerHour, 8);
145    }
146
147    public function getWordsPerMinute(User $user): int
148    {
149        $userWordPerMinute = FlyCutUsage::WORDS_PER_MINUTE;
150
151        if (filled($user->setting) && !empty($user->setting->words_per_minute)) {
152            $userWordPerMinute = $user->setting->words_per_minute;
153        }
154
155        if (!empty($user->company_id) && strtolower($user->status) == 'active') {
156            $companySetting = Setting::where('company_id', $user->company_id)->first();
157            if ($companySetting && $companySetting->override_user_words_per_minute && !empty($companySetting->words_per_minute)) {
158                $userWordPerMinute = $companySetting->words_per_minute;
159            }
160        }
161
162        return $userWordPerMinute;
163    }
164
165    public function getCompanyDefaultSetting()
166    {
167        return [
168            'wage_per_hour' => FlyCutUsage::WAGE_PER_HOUR,
169            'words_per_minute' => FlyCutUsage::WORDS_PER_MINUTE,
170            'override_user_wage_per_hour' => false,
171            'override_user_typing_style' => false,
172            'override_user_flygrammar' => false,
173            'override_user_flyrewrite' => false,
174            'typing_style' => 'all',
175            'fly_rewrite' => 'enabled',
176            'fly_grammar' => 'enabled',
177            'fly_grammar_default_language' => 'en_US'
178        ];
179    }
180
181    /**
182     * Get the time saved in hours.
183     */
184    public function getTimeSaved(User $user, int $charactersSaved): float
185    {
186        $userWordPerMinute = $this->getWordsPerMinute($user);
187
188        $characterPerHour = $userWordPerMinute * 300;
189
190        return round($charactersSaved / $characterPerHour, 8);
191    }
192
193    /**
194     * Get the time saved in hours for old records.
195     */
196    public function getOldTimeSaved($from, $hubspotRecord): float
197    {
198        $tRecord = $this->transformHubSpotRecord($hubspotRecord);
199
200        if (! $tRecord) {
201            return 0;
202        }
203
204        $user = User::where('id', $hubspotRecord['flymsg_id'])->first();
205        $userWordPerMinute = $this->getWordsPerMinute($user);
206
207        $characterPerHour = $userWordPerMinute * 300;
208
209        //Estimate
210        $difference = $this->getOldCharactersTyped($from, $hubspotRecord) - ($hubspotRecord->number_of_flycuts_created * 5);
211
212        $charactersSaved = $difference > 0 ? $difference : 0;
213
214        return $charactersSaved / $characterPerHour;
215    }
216
217    /**
218     * Get the characters typed for old records.
219     */
220    public function getOldCharactersTyped($from, $hubspotRecord): int
221    {
222        $tRecord = $this->transformHubSpotRecord($hubspotRecord);
223
224        if (! $tRecord) {
225            return 0;
226        }
227
228        $filtered = collect(array_filter($tRecord, function ($key) use ($from) {
229            return Carbon::parse($key)->gte(Carbon::parse($from));
230        }, ARRAY_FILTER_USE_KEY));
231
232        return $filtered->sum(function ($value) {
233            return $value;
234        });
235    }
236
237    /**
238     * Get chart data from old records.
239     */
240    public function getOldChart(string $from, $hubspotRecord)
241    {
242        $tRecord = $this->transformHubSpotRecord($hubspotRecord);
243
244        // Get user avergae charcter count for flycuts
245        $flymsg_id = $hubspotRecord['flymsg_id'] ?? null;
246        $average = 1;
247        $user = User::where('_id', $flymsg_id)->first();
248
249        if (isset($user['average_charactors_count']) && $user['average_charactors_count'] != null) {
250            $average = $user['average_charactors_count'];
251        } else {
252            $shortcuts = ShortcutWithUsage::where('user_id', $flymsg_id)
253                ->where('created_at', '<=', Carbon::createFromFormat('Y-m-d', '2023-1-24'))
254                ->select('text', 'charactors_count')->get();
255            if (isset($shortcuts) && count($shortcuts) > 0) {
256                $charactors_counts = [];
257                foreach ($shortcuts as $shortcutHtmlArray) {
258                    if ($shortcutHtmlArray['charactors_count']) {
259                        $charactors_counts[] = $shortcutHtmlArray['charactors_count'];
260                    } else {
261                        $charactors_counts[] = strlen(strip_tags($shortcutHtmlArray['text']));
262                    }
263                }
264                $a = array_filter($charactors_counts);
265                $average = array_sum($a) / count($a);
266                $user['average_charactors_count'] = $average;
267                $user->save();
268            }
269        }
270
271        if (! $tRecord) {
272            return null;
273        }
274
275        $filtered = array_reverse(array_filter($tRecord, function ($key) use ($from) {
276            return Carbon::parse($key)->gte(Carbon::parse($from));
277        }, ARRAY_FILTER_USE_KEY), true);
278
279        $mutated = [];
280
281        array_map(function ($key, $value) use ($hubspotRecord, &$mutated, $average, $user, $from) {
282            //Estimate
283            $difference = $value - ($hubspotRecord->number_of_flycuts_created * 5);
284
285            $charactersSaved = $difference > 0 ? $difference : 0;
286
287            // old $timeSaved = $charactersSaved / $characterPerHour;
288            $timeSaved = $this->getTimeSaved($user, $charactersSaved);
289            $costSaved = $this->getCostSaved($user, $timeSaved, Carbon::parse($from));
290
291            $keyArray = explode(' ', $key);
292
293            $flycuts_used = $value / ($average * 0.5);
294
295            $mutated[@$keyArray[0]] =
296                [
297                    'flycut_count' => ceil($flycuts_used),
298                    'characters_typed' => $value,
299                    'cost_saved' => $timeSaved,
300                    'time_saved' => $costSaved,
301                ];
302            if (isset($mutated['totalflycuts_used'])) {
303                $mutated['totalflycuts_used'] = $mutated['totalflycuts_used'] + ceil($flycuts_used);
304            } else {
305                $mutated['totalflycuts_used'] = ceil($flycuts_used);
306            }
307        }, array_keys($filtered), array_values($filtered));
308
309        return $mutated;
310    }
311
312    public function transformHubSpotRecord($hubspotRecord)
313    {
314        $monthlyRecord = @$hubspotRecord->total___of_characters_typed_monthly_by_flymsg_by_user;
315
316        //$monthlyRecord = "136050 - Jan 2023.   86228 - Dec 2022.   524720 - Nov 2022.   141441 - Oct 2022.   378095 - Sep 2022.   158766 - Aug 2022.   109886 - Jul 2022.   173300 - Jun 2022.   99031 - May 2022.   175428 - Apr 2022.   0 - Mar 2022.   0 - Feb 2022.   0 - Jan 2022.   ";
317
318        if (! $monthlyRecord || empty($monthlyRecord)) {
319            return null;
320        }
321
322        $record = array_map('trim', explode('.', $monthlyRecord));
323
324        $tRecord = [];
325        array_map(function ($each) use (&$tRecord) {
326            $exploded = explode(' - ', $each);
327
328            if (filled(@$exploded[1])) {
329                $tRecord[@$exploded[1]] = (int) $exploded[0];
330            }
331        }, $record);
332
333        return $tRecord;
334    }
335
336    public function transformHubSpotRecordToRawChartData($hubspotRecord)
337    {
338        $monthlyRecord = @$hubspotRecord->total___of_characters_typed_monthly_by_flymsg_by_user;
339
340        if (! $monthlyRecord || empty($monthlyRecord)) {
341            return null;
342        }
343
344        $user = User::where('id', $hubspotRecord['flymsg_id'])->first();
345        $record = array_map('trim', explode('.', $monthlyRecord));
346
347        return array_map(function ($each) use ($hubspotRecord, $user) {
348            $exploded = explode(' - ', $each);
349
350            if (filled(@$exploded[1])) {
351                //Estimate
352                $charactersSaved = (int) $exploded[0] - ($hubspotRecord->number_of_flycuts_created * 5);
353
354                $charactersSaved = $charactersSaved > 0 ? $charactersSaved : 0;
355
356                // old $timeSaved = $charactersSaved / $characterPerHour;
357                $timeSaved = $this->getTimeSaved($user, $charactersSaved);
358                $costSaved = $this->getCostSaved($user, $timeSaved, now());
359
360                return [
361                    'month_year' => @$exploded[1],
362                    'flycuts_used' => 0,
363                    'characters_typed' => (int) $exploded[0],
364                    'characters_saved' => $charactersSaved,
365                    'time_saved' => $timeSaved,
366                    'cost_saved' => $costSaved,
367                ];
368            }
369
370            return [];
371        }, $record);
372    }
373}