Minor: use compile-time constants instead of string literals
[idea/community.git] / plugins / stats-collector / src / com / intellij / stats / personalization / impl / DoubleFeatureFactors.kt
1 /*
2  * Copyright 2000-2017 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.intellij.stats.personalization.impl
18
19 import com.intellij.stats.personalization.*
20 import com.jetbrains.completion.ranker.features.DoubleFeature
21 import com.jetbrains.completion.ranker.features.impl.FeatureUtils
22
23 /**
24  * @author Vitaliy.Bibaev
25  */
26 class DoubleFeatureReader(factor: DailyAggregatedDoubleFactor)
27     : UserFactorReaderBase(factor) {
28     fun calculateAverageValue(): Double? {
29         return FactorsUtil.calculateAverageByAllDays(factor)
30     }
31
32     fun calculateVariance(): Double? = FactorsUtil.calculateVarianceByAllDays(factor)
33
34     fun min(): Double? {
35         return factor.aggregateMin()["min"]
36     }
37
38     fun max(): Double? {
39         return factor.aggregateMax()["max"]
40     }
41
42     fun undefinedRatio(): Double? {
43         val sums = factor.aggregateSum()
44         val total = sums["count"] ?: return null
45         if (total == 0.0) return null
46
47         return sums.getOrDefault(FeatureUtils.UNDEFINED, 0.0) / total
48     }
49 }
50
51 class DoubleFeatureUpdater(factor: MutableDoubleFactor) : UserFactorUpdaterBase(factor) {
52     fun update(value: Any?) {
53         if (value == null) {
54             factor.incrementOnToday(FeatureUtils.UNDEFINED)
55         } else {
56             val doubleValue = value.asDouble()
57             factor.updateOnDate(DateUtil.today()) {
58                 FactorsUtil.updateAverageAndVariance(this, doubleValue)
59                 compute("max", { _, old -> if (old == null) doubleValue else maxOf(old, doubleValue) })
60                 compute("min", { _, old -> if (old == null) doubleValue else minOf(old, doubleValue) })
61             }
62         }
63     }
64
65     private fun Any.asDouble(): Double {
66         if (this is Number) return this.toDouble()
67         return this.toString().toDouble()
68     }
69 }
70
71 abstract class DoubleFeatureUserFactorBase(prefix: String, feature: DoubleFeature) :
72         UserFactorBase<DoubleFeatureReader>("${prefix}DoubleFeature:${feature.name}$",
73                 UserFactorDescriptions.doubleFeatureDescriptor(feature))
74
75 class AverageDoubleFeatureValue(feature: DoubleFeature) : DoubleFeatureUserFactorBase("avg", feature) {
76     override fun compute(reader: DoubleFeatureReader): String? = reader.calculateAverageValue()?.toString()
77 }
78
79 class MinDoubleFeatureValue(feature: DoubleFeature) : DoubleFeatureUserFactorBase("min", feature) {
80     override fun compute(reader: DoubleFeatureReader): String? = reader.min()?.toString()
81 }
82
83 class MaxDoubleFeatureValue(feature: DoubleFeature) : DoubleFeatureUserFactorBase("max", feature) {
84     override fun compute(reader: DoubleFeatureReader): String? = reader.max()?.toString()
85 }
86
87 class UndefinedDoubleFeatureValueRatio(feature: DoubleFeature) : DoubleFeatureUserFactorBase("undefinedRatio", feature) {
88     override fun compute(reader: DoubleFeatureReader): String? = reader.undefinedRatio()?.toString()
89 }
90
91 class VarianceDoubleFeatureValue(feature: DoubleFeature) : DoubleFeatureUserFactorBase("variance", feature) {
92     override fun compute(reader: DoubleFeatureReader): String? = reader.calculateVariance()?.toString()
93 }