Skip to content

Commit ec00c51

Browse files
committed
delayed value selection for complex rules
1 parent ce9246a commit ec00c51

File tree

69 files changed

+683
-90
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+683
-90
lines changed

core/common/src/main/java/com/example/util/simpletimetracker/core/mapper/RecordTagValueMapper.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,26 @@ class RecordTagValueMapper @Inject constructor(
3030
val tagValue = mapTagValue(value, valueSuffix)
3131
return resourceRepo.getString(R.string.separator_template, name, "($tagValue)")
3232
}
33+
34+
fun getName(
35+
tagId: Long,
36+
name: String,
37+
value: Double?,
38+
valueSuffix: String,
39+
valueOnStartIds: List<Long>,
40+
): String {
41+
return when {
42+
value != null -> getNameWithValue(
43+
name = name,
44+
value = value,
45+
valueSuffix = valueSuffix,
46+
)
47+
tagId in valueOnStartIds -> resourceRepo.getString(
48+
R.string.separator_template,
49+
name,
50+
"(${resourceRepo.getString(R.string.change_complex_tag_value_set_later)})",
51+
)
52+
else -> name
53+
}
54+
}
3355
}

core/src/main/java/com/example/util/simpletimetracker/core/dialog/TypesSelectionDialogListener.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ interface TypesSelectionDialogListener {
88
tag: String?,
99
dataIds: List<Long>,
1010
tagValues: List<RecordBase.Tag>,
11+
selectValueOnStartTagIds: List<Long> = emptyList(),
1112
)
1213
}

core/src/main/java/com/example/util/simpletimetracker/core/extension/ViewDataExensions.kt

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -280,11 +280,19 @@ fun RangeLength.toParams(): RangeLengthParams {
280280
}
281281
}
282282

283-
fun RecordDataSelectionDialogResult.toParams(): List<RecordTagSelectionParams.Field> {
284-
return fields.map {
285-
when (it) {
286-
is RecordDataSelectionDialogResult.Field.Tags -> RecordTagSelectionParams.Field.Tags
287-
is RecordDataSelectionDialogResult.Field.Comment -> RecordTagSelectionParams.Field.Comment
288-
}
289-
}
283+
fun RecordDataSelectionDialogResult.toParams(): RecordTagSelectionFields {
284+
return RecordTagSelectionFields(
285+
fields = fields.map {
286+
when (it) {
287+
is RecordDataSelectionDialogResult.Field.Tags -> RecordTagSelectionParams.Field.Tags
288+
is RecordDataSelectionDialogResult.Field.Comment -> RecordTagSelectionParams.Field.Comment
289+
}
290+
},
291+
requiredTagValueSelectionTagIds = requiredTagValueSelectionTagIds,
292+
)
290293
}
294+
295+
data class RecordTagSelectionFields(
296+
val fields: List<RecordTagSelectionParams.Field>,
297+
val requiredTagValueSelectionTagIds: List<Long>,
298+
)

core/src/main/java/com/example/util/simpletimetracker/core/mapper/CategoryViewDataMapper.kt

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -119,24 +119,22 @@ class CategoryViewDataMapper @Inject constructor(
119119
types: Map<Long, RecordType>,
120120
isDarkTheme: Boolean,
121121
isFiltered: Boolean = false,
122+
valueOnStartIds: List<Long> = emptyList(),
122123
): CategoryViewData.Record {
123124
val viewData = mapRecordTag(
124125
tag = tag,
125126
types = types,
126127
isDarkTheme = isDarkTheme,
127128
isFiltered = isFiltered,
128129
)
129-
val value = tagData?.numericValue
130-
return if (value != null) {
131-
val newName = recordTagValueMapper.getNameWithValue(
132-
name = viewData.name,
133-
value = value,
134-
valueSuffix = tag.valueSuffix,
135-
)
136-
return viewData.copy(name = newName)
137-
} else {
138-
viewData
139-
}
130+
val newName = recordTagValueMapper.getName(
131+
tagId = tag.id,
132+
name = tag.name,
133+
value = tagData?.numericValue,
134+
valueSuffix = tag.valueSuffix,
135+
valueOnStartIds = valueOnStartIds,
136+
)
137+
return viewData.copy(name = newName)
140138
}
141139

142140
fun groupToTagGroups(

core/src/main/java/com/example/util/simpletimetracker/core/mapper/ComplexRuleViewDataMapper.kt

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ class ComplexRuleViewDataMapper @Inject constructor(
9595
tagsOrder: List<Long>,
9696
): List<ViewHolderType> {
9797
val action = rule.action
98+
val actionAssignTagValueOnStartIds = rule.actionAssignTagValueOnStartIds.toList()
9899
val data = when (action) {
99100
is ComplexRule.Action.AllowMultitasking,
100101
is ComplexRule.Action.DisallowMultitasking,
@@ -112,20 +113,24 @@ class ComplexRuleViewDataMapper @Inject constructor(
112113
)
113114
result += data.mapNotNull { tagValue ->
114115
val tag = tagsMap[tagValue.tagId] ?: return@mapNotNull null
116+
val text = recordTagValueMapper.getName(
117+
tagId = tagValue.tagId,
118+
name = tag.name,
119+
value = tagValue.numericValue,
120+
valueSuffix = tag.valueSuffix,
121+
valueOnStartIds = actionAssignTagValueOnStartIds,
122+
)
115123
ListElementViewData(
116-
text = tagValue.numericValue?.let { value ->
117-
recordTagValueMapper.getNameWithValue(
118-
name = tag.name,
119-
value = value,
120-
valueSuffix = tag.valueSuffix,
121-
)
122-
} ?: tag.name,
124+
text = text,
123125
icon = recordTagViewDataMapper.mapIcon(
124126
tag = tag,
125127
types = typesMap,
126128
)?.let(iconMapper::mapIcon),
127129
color = colorMapper.mapToColorInt(
128-
color = tag.color,
130+
color = recordTagViewDataMapper.mapColor(
131+
tag = tag,
132+
types = typesMap,
133+
),
129134
isDarkTheme = isDarkTheme,
130135
),
131136
)

core/src/main/java/com/example/util/simpletimetracker/core/utils/TestUtils.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ class TestUtils @Inject constructor(
343343
numericValue = assignTagValues[name],
344344
)
345345
},
346+
actionAssignTagValueOnStartIds = emptySet(),
346347
conditionStartingTypeIds = getTypeIds(availableTypes, startingTypeNames),
347348
conditionCurrentTypeIds = getTypeIds(availableTypes, currentTypeNames),
348349
conditionDaysOfWeek = daysOfWeek.toSet(),

data_local/src/main/java/com/example/util/simpletimetracker/data_local/backup/BackupRepoImpl.kt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,10 @@ class BackupRepoImpl @Inject constructor(
633633
.mapDaysOfWeek(complexRule.conditionDaysOfWeek)
634634
val disallowOnlyPreviousString = (if (complexRule.actionDisallowOnlyPrevious) 1 else 0)
635635
.toString()
636-
val valuesString = complexRuleTagValuesMapper.serialize(complexRule.actionAssignTagValues)
636+
val valuesString = complexRuleTagValuesMapper.serialize(
637+
data = complexRule.actionAssignTagValues,
638+
tagIdsToSelectValueOnStart = complexRule.actionAssignTagValueOnStartIds,
639+
)
637640

638641
return String.format(
639642
"$ROW_COMPLEX_RULE\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
@@ -949,8 +952,11 @@ class BackupRepoImpl @Inject constructor(
949952
private fun complexRuleFromBackupString(parts: List<String>): ComplexRule {
950953
val assignTagIds = parts.getOrNull(4)?.split(",")
951954
?.mapNotNull { it.toLongOrNull() }.orEmpty().toSet()
952-
val assignTagValues = complexRuleTagValuesMapper.parse(parts.getOrNull(9))
953-
.associateBy { it.tagId }
955+
val parsedTagValues = complexRuleTagValuesMapper.parse(parts.getOrNull(9))
956+
val assignTagValues = parsedTagValues.tagsWithValues.associateBy { it.tagId }
957+
val assignTagValueOnStartIds = assignTagIds
958+
.filter { parsedTagValues.tagIdsToSelectValueOnStart.contains(it) }
959+
.toSet()
954960

955961
return ComplexRule(
956962
id = parts.getOrNull(1)?.toLongOrNull().orZero(),
@@ -965,6 +971,7 @@ class BackupRepoImpl @Inject constructor(
965971
actionAssignTagValues = assignTagIds.map {
966972
RecordBase.Tag(tagId = it, numericValue = assignTagValues[it]?.numericValue)
967973
},
974+
actionAssignTagValueOnStartIds = assignTagValueOnStartIds,
968975
conditionStartingTypeIds = parts.getOrNull(5)?.split(",")
969976
?.mapNotNull { it.toLongOrNull() }.orEmpty().toSet(),
970977
conditionCurrentTypeIds = parts.getOrNull(6)?.split(",")

data_local/src/main/java/com/example/util/simpletimetracker/data_local/complexRule/ComplexRuleDataLocalMapper.kt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@ class ComplexRuleDataLocalMapper @Inject constructor(
1212

1313
fun map(dbo: ComplexRuleDBO): ComplexRule {
1414
val assignTagIds = mapIds(dbo.actionSetTagIds)
15-
val assignTagValues = complexRuleTagValuesMapper.parse(dbo.actionSetTagValues)
16-
.associateBy { it.tagId }
15+
val parsedValues = complexRuleTagValuesMapper.parse(dbo.actionSetTagValues)
16+
val assignTagValues = parsedValues.tagsWithValues.associateBy { it.tagId }
17+
val assignTagValueOnStartIds = assignTagIds
18+
.filter { parsedValues.tagIdsToSelectValueOnStart.contains(it) }
19+
.toSet()
1720

1821
return ComplexRule(
1922
id = dbo.id,
@@ -23,6 +26,7 @@ class ComplexRuleDataLocalMapper @Inject constructor(
2326
actionAssignTagValues = assignTagIds.map {
2427
RecordBase.Tag(tagId = it, numericValue = assignTagValues[it]?.numericValue)
2528
},
29+
actionAssignTagValueOnStartIds = assignTagValueOnStartIds,
2630
conditionStartingTypeIds = mapIds(dbo.conditionStartingTypeIds),
2731
conditionCurrentTypeIds = mapIds(dbo.conditionCurrentTypeIds),
2832
conditionDaysOfWeek = daysOfWeekDataLocalMapper
@@ -37,7 +41,10 @@ class ComplexRuleDataLocalMapper @Inject constructor(
3741
action = mapActionType(domain.action),
3842
actionDisallowOnlyPrevious = domain.actionDisallowOnlyPrevious,
3943
actionSetTagIds = mapIds(domain.actionAssignTagIds),
40-
actionSetTagValues = complexRuleTagValuesMapper.serialize(domain.actionAssignTagValues),
44+
actionSetTagValues = complexRuleTagValuesMapper.serialize(
45+
data = domain.actionAssignTagValues,
46+
tagIdsToSelectValueOnStart = domain.actionAssignTagValueOnStartIds,
47+
),
4148
conditionStartingTypeIds = mapIds(domain.conditionStartingTypeIds),
4249
conditionCurrentTypeIds = mapIds(domain.conditionCurrentTypeIds),
4350
conditionDaysOfWeek = daysOfWeekDataLocalMapper

data_local/src/main/java/com/example/util/simpletimetracker/data_local/complexRule/ComplexRuleTagValuesMapper.kt

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,58 @@ class ComplexRuleTagValuesMapper @Inject constructor(
88
private val recordTagValueFormatMapper: RecordTagValueFormatMapper,
99
) {
1010

11-
fun serialize(data: List<RecordBase.Tag>): String {
12-
return data.mapNotNull { tag ->
11+
fun serialize(
12+
data: List<RecordBase.Tag>,
13+
tagIdsToSelectValueOnStart: Set<Long>,
14+
): String {
15+
val numericEntries = data.mapNotNull { tag ->
1316
val value = tag.numericValue ?: return@mapNotNull null
1417
"${tag.tagId}:${recordTagValueFormatMapper.map(value)}"
15-
}.joinToString(separator = ",")
18+
}
19+
val laterEntries = tagIdsToSelectValueOnStart
20+
.filter { tagId -> data.none { it.tagId == tagId && it.numericValue != null } }
21+
.map { tagId -> "$tagId:later" }
22+
return (numericEntries + laterEntries).joinToString(separator = ",")
1623
}
1724

18-
fun parse(data: String?): List<RecordBase.Tag> {
19-
if (data == null || data.isBlank()) return emptyList()
25+
fun parse(data: String?): ParsedTagValues {
26+
if (data.isNullOrBlank()) {
27+
return ParsedTagValues(tagsWithValues = emptyList(), tagIdsToSelectValueOnStart = emptySet())
28+
}
29+
30+
val numericValues = mutableMapOf<Long, Double>()
31+
val tagIdsToSelectValueOnStart = mutableSetOf<Long>()
2032

21-
return data.split(',').mapNotNull { entry ->
33+
data.split(',').forEach { entry ->
2234
val parts = entry.split(':', limit = 2)
23-
if (parts.size != 2) return@mapNotNull null
24-
RecordBase.Tag(
25-
tagId = parts[0].toLongOrNull() ?: return@mapNotNull null,
26-
numericValue = parts[1].toDoubleOrNull() ?: return@mapNotNull null,
27-
)
35+
if (parts.size != 2) return@forEach
36+
val tagId = parts[0].toLongOrNull() ?: return@forEach
37+
when (parts[1]) {
38+
"later" -> {
39+
if (tagId !in numericValues) {
40+
tagIdsToSelectValueOnStart.add(tagId)
41+
}
42+
}
43+
else -> {
44+
val numericValue = parts[1].toDoubleOrNull() ?: return@forEach
45+
numericValues[tagId] = numericValue
46+
tagIdsToSelectValueOnStart.remove(tagId)
47+
}
48+
}
2849
}
50+
51+
val tagsWithValues = numericValues.map { (tagId, numericValue) ->
52+
RecordBase.Tag(tagId = tagId, numericValue = numericValue)
53+
}
54+
55+
return ParsedTagValues(
56+
tagsWithValues = tagsWithValues,
57+
tagIdsToSelectValueOnStart = tagIdsToSelectValueOnStart,
58+
)
2959
}
60+
61+
data class ParsedTagValues(
62+
val tagsWithValues: List<RecordBase.Tag>,
63+
val tagIdsToSelectValueOnStart: Set<Long>,
64+
)
3065
}

domain/src/main/java/com/example/util/simpletimetracker/domain/complexRule/interactor/ComplexRuleProcessActionInteractor.kt

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,32 @@ class ComplexRuleProcessActionInteractor @Inject constructor(
4848
.orEmpty()
4949

5050
val additionalTags = linkedMapOf<Long, RecordBase.Tag>()
51-
assignTagRules.flatMap { it.actionAssignTagValues }.forEach { tag ->
52-
val existing = additionalTags[tag.tagId]
53-
// Tags with values takes precedence.
54-
if (existing == null || (existing.numericValue == null && tag.numericValue != null)) {
55-
additionalTags[tag.tagId] = tag
51+
val laterTagIds = mutableSetOf<Long>()
52+
assignTagRules.forEach { rule ->
53+
laterTagIds.addAll(rule.actionAssignTagValueOnStartIds)
54+
rule.actionAssignTagValues.forEach { tag ->
55+
val existing = additionalTags[tag.tagId]
56+
// Tags with values takes precedence.
57+
if (existing == null || (existing.numericValue == null && tag.numericValue != null)) {
58+
additionalTags[tag.tagId] = tag
59+
}
60+
}
61+
}
62+
63+
val filteredLaterTagIds = laterTagIds
64+
.filter { it in additionalTags.keys }
65+
.toMutableSet()
66+
additionalTags.values.forEach { tag ->
67+
if (tag.numericValue != null) {
68+
filteredLaterTagIds.remove(tag.tagId)
5669
}
5770
}
5871

5972
return Result(
6073
isMultitaskingAllowed = isMultitaskingAllowed,
6174
disallowOnlyPreviousTypeIds = disallowOnlyPreviousTypeIds,
6275
tags = additionalTags.values.toList(),
76+
tagIdsToSelectValueOnStart = filteredLaterTagIds,
6377
)
6478
}
6579

@@ -89,5 +103,6 @@ class ComplexRuleProcessActionInteractor @Inject constructor(
89103
val isMultitaskingAllowed: ResultContainer<Boolean>,
90104
val disallowOnlyPreviousTypeIds: Set<Long>,
91105
val tags: List<RecordBase.Tag>,
106+
val tagIdsToSelectValueOnStart: Set<Long>,
92107
)
93108
}

0 commit comments

Comments
 (0)