diff --git a/pom.xml b/pom.xml
index 38e2d2e..ef8c52a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,7 +15,7 @@
Down of war wiki
17
- 1.8.22
+ 2.2.0
3.3.1
diff --git a/src/main/kotlin/com/dowstats/Metadata.kt b/src/main/kotlin/com/dowstats/Metadata.kt
index b58f35c..0ae534b 100644
--- a/src/main/kotlin/com/dowstats/Metadata.kt
+++ b/src/main/kotlin/com/dowstats/Metadata.kt
@@ -4,4 +4,13 @@ object Metadata {
const val USER_ROLE = "USER"
+ object Requirements {
+ val REFERENCE_REQUIREMENT_POP = "requirements\\required_total_pop.lua"
+ val REFERENCE_REQUIREMENT_ADDON = "requirements\\local_required_addon.lua"
+ val REFERENCE_GLOBAL_REQUIREMENT_ADDON = "requirements\\global_required_addon.lua"
+ val REFERENCE_REQUIREMENT_STRUCTURE_EITHER = "requirements\\required_structure_either.lua"
+ val REFERENCE_REQUIREMENT_STRUCTURE = "requirements\\required_structure.lua"
+ val REFERENCE_REQUIREMENT_RESEARCH = "requirements\\required_research.lua"
+ }
+
}
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/data/dto/AreaEffect.kt b/src/main/kotlin/com/dowstats/data/dto/AreaEffect.kt
new file mode 100644
index 0000000..6e88f69
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/data/dto/AreaEffect.kt
@@ -0,0 +1,13 @@
+package com.dowstats.data.dto
+
+data class AreaEffect(
+ val minDamage: Double,
+ val maxDamage: Double,
+ val damageRadius: Double,
+ val throwForceMin: Double,
+ val throwForceMax: Double,
+ val minDamageValue: Double,
+ val moraleDamage: Double,
+ val weaponDmgMap: Map,
+ val defaultArmorPiercing: Double,
+)
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/data/dto/ResourceIncome.kt b/src/main/kotlin/com/dowstats/data/dto/ResourceIncome.kt
new file mode 100644
index 0000000..29e1e4c
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/data/dto/ResourceIncome.kt
@@ -0,0 +1,7 @@
+package com.dowstats.data.dto
+
+data class ResourceIncome(
+ val faith: Double?,
+ val power: Double?,
+ val requisition: Double?,
+)
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/data/dto/UiInfo.kt b/src/main/kotlin/com/dowstats/data/dto/UiInfo.kt
new file mode 100644
index 0000000..eb63016
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/data/dto/UiInfo.kt
@@ -0,0 +1,7 @@
+package com.dowstats.data.dto
+
+data class UiInfo (
+ val name: String?,
+ val description: String?,
+ val iconPath: String?,
+)
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/data/dto/controllers/EntityCompressDto.kt b/src/main/kotlin/com/dowstats/data/dto/controllers/EntityCompressDto.kt
new file mode 100644
index 0000000..7aa7f50
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/data/dto/controllers/EntityCompressDto.kt
@@ -0,0 +1,48 @@
+package com.dowstats.data.dto.controllers
+
+import com.dowstats.data.entities.Building
+import com.dowstats.data.entities.DowUnit
+import com.dowstats.data.entities.Sergeant
+import com.dowstats.data.entities.Weapon
+
+
+data class EntityCompressDto(
+ val name: String?,
+ val icon: String?,
+ val id: Long,
+ val filename: String?,
+)
+
+object EntityCompressDtoObject {
+ fun Sergeant.compressDto(): EntityCompressDto =
+ EntityCompressDto(
+ this.name,
+ this.icon,
+ this.id!!,
+ this.filename
+ )
+
+ fun DowUnit.compressDto(): EntityCompressDto =
+ EntityCompressDto(
+ this.name,
+ this.icon,
+ this.id!!,
+ this.filenameSquad + ";" + this.filenameUnit
+ )
+
+ fun Building.compressDto(): EntityCompressDto =
+ EntityCompressDto(
+ this.name,
+ this.icon,
+ this.id!!,
+ this.filename
+ )
+
+ fun Weapon.compressDto(): EntityCompressDto =
+ EntityCompressDto(
+ this.name,
+ this.icon,
+ this.id!!,
+ this.filename
+ )
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/data/dto/controllers/building/AddonModifierDto.kt b/src/main/kotlin/com/dowstats/data/dto/controllers/ModifierDto.kt
similarity index 50%
rename from src/main/kotlin/com/dowstats/data/dto/controllers/building/AddonModifierDto.kt
rename to src/main/kotlin/com/dowstats/data/dto/controllers/ModifierDto.kt
index e7226ec..9e78e49 100644
--- a/src/main/kotlin/com/dowstats/data/dto/controllers/building/AddonModifierDto.kt
+++ b/src/main/kotlin/com/dowstats/data/dto/controllers/ModifierDto.kt
@@ -1,8 +1,9 @@
-package com.dowstats.data.dto.controllers.building
+package com.dowstats.data.dto.controllers
-data class AddonModifierDto (
+data class ModifierDto (
val id: Long,
val reference: String?,
val usageType: String?,
val value: Double?,
+ val target: String? = null,
)
diff --git a/src/main/kotlin/com/dowstats/data/dto/controllers/RequirementDto.kt b/src/main/kotlin/com/dowstats/data/dto/controllers/RequirementDto.kt
new file mode 100644
index 0000000..fbde80a
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/data/dto/controllers/RequirementDto.kt
@@ -0,0 +1,20 @@
+package com.dowstats.data.dto.controllers
+
+import com.dowstats.data.dto.controllers.building.BuildingAddonShortDto
+import com.dowstats.data.dto.controllers.building.BuildingShortDto
+import com.dowstats.data.dto.controllers.research.ResearchShortDto
+
+data class RequirementDto (
+ val requirementBuildings: Set,
+ val requirementBuildingsEither: Set,
+ val requirementResearches: Set,
+ val requireAddon: BuildingAddonShortDto?,
+ val requirementsGlobalAddons: Set?,
+ val requiredTotalPop: Int?,
+ val replaceWhenDone: Boolean = false,
+)
+
+data class RequirementResearchDto(
+ val researchShortDto: ResearchShortDto,
+ val researchMustNotBeComplete: Boolean,
+)
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/data/dto/controllers/SergeantDto.kt b/src/main/kotlin/com/dowstats/data/dto/controllers/SergeantDto.kt
index 0b07f4d..ae2e346 100644
--- a/src/main/kotlin/com/dowstats/data/dto/controllers/SergeantDto.kt
+++ b/src/main/kotlin/com/dowstats/data/dto/controllers/SergeantDto.kt
@@ -1,5 +1,7 @@
package com.dowstats.data.dto.controllers
+import com.dowstats.data.dto.controllers.research.ResearchShortDto
+
data class SergeantDto(
val id: Long?,
@@ -27,4 +29,5 @@ data class SergeantDto(
val detectRadius: Int?,
val icon: String?,
val weapons: List?,
+ val affectedResearches: Set,
)
diff --git a/src/main/kotlin/com/dowstats/data/dto/controllers/SergeantUnitShortDto.kt b/src/main/kotlin/com/dowstats/data/dto/controllers/SergeantUnitShortDto.kt
new file mode 100644
index 0000000..753a971
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/data/dto/controllers/SergeantUnitShortDto.kt
@@ -0,0 +1,9 @@
+package com.dowstats.data.dto.controllers
+
+data class SergeantUnitShortDto(
+ val id: Long?,
+ val filename: String,
+ val name: String?,
+ val icon: String?,
+ val unit: EntityCompressDto
+)
diff --git a/src/main/kotlin/com/dowstats/data/dto/controllers/UnitFullDto.kt b/src/main/kotlin/com/dowstats/data/dto/controllers/UnitFullDto.kt
index b5cc754..7edc77f 100644
--- a/src/main/kotlin/com/dowstats/data/dto/controllers/UnitFullDto.kt
+++ b/src/main/kotlin/com/dowstats/data/dto/controllers/UnitFullDto.kt
@@ -1,5 +1,7 @@
package com.dowstats.data.dto.controllers
+import com.dowstats.data.dto.controllers.research.ResearchShortDto
+
data class UnitFullDto(
val id: Long,
@@ -35,17 +37,19 @@ data class UnitFullDto(
val moveSpeed: Int?,
val sightRadius: Int?,
val detectRadius: Int?,
- val reinforceCostRequisition: Int?,
- val reinforceCostPower: Int?,
- val reinforceCostPopulation: Int?,
- val reinforceCostFaith: Int?,
- val reinforceCostSouls: Int?,
+ val reinforceCostRequisition: Double?,
+ val reinforceCostPower: Double?,
+ val reinforceCostPopulation: Double?,
+ val reinforceCostFaith: Double?,
+ val reinforceCostSouls: Double?,
val reinforceTime: Int?,
val repairMax: Int?,
val repairSpeed: Int?,
+ val repairCostPercent: Int?,
val maxSergeants: Int?,
val icon: String?,
val modId: Long,
val sergeants: Set?,
val weapons: Set?,
+ val affectedResearches: Set,
)
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/data/dto/controllers/WeaponDto.kt b/src/main/kotlin/com/dowstats/data/dto/controllers/WeaponDto.kt
index 2c28781..9116cb4 100644
--- a/src/main/kotlin/com/dowstats/data/dto/controllers/WeaponDto.kt
+++ b/src/main/kotlin/com/dowstats/data/dto/controllers/WeaponDto.kt
@@ -1,12 +1,14 @@
package com.dowstats.data.dto.controllers
+import com.dowstats.data.dto.controllers.research.ResearchShortDto
+
data class WeaponDto(
val id: Long?,
val filename: String,
val name: String?,
val description: String?,
- val costRequisition: Int?,
- val costPower: Int?,
+ val costRequisition: Double?,
+ val costPower: Double?,
val costTimeSeconds: Int?,
val accuracy: Double?,
val reloadTime: Double?,
@@ -27,5 +29,6 @@ data class WeaponDto(
val icon: String?,
val haveEquipButton: Boolean,
val modId: Long?,
- val weaponArmorPiercing: List
+ val weaponArmorPiercing: List,
+ val affectedResearches: Set,
)
diff --git a/src/main/kotlin/com/dowstats/data/dto/controllers/WeaponUnitShortDto.kt b/src/main/kotlin/com/dowstats/data/dto/controllers/WeaponUnitShortDto.kt
new file mode 100644
index 0000000..136bee0
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/data/dto/controllers/WeaponUnitShortDto.kt
@@ -0,0 +1,10 @@
+package com.dowstats.data.dto.controllers
+
+data class WeaponUnitShortDto(
+ val id: Long?,
+ val filename: String,
+ val name: String?,
+ val units: Set,
+ val sergeants: Set,
+ val buildings: Set
+)
diff --git a/src/main/kotlin/com/dowstats/data/dto/controllers/building/AddonRequirementDto.kt b/src/main/kotlin/com/dowstats/data/dto/controllers/building/AddonRequirementDto.kt
deleted file mode 100644
index 20162dc..0000000
--- a/src/main/kotlin/com/dowstats/data/dto/controllers/building/AddonRequirementDto.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.dowstats.data.dto.controllers.building
-
-data class AddonRequirementDto (
- val requirementBuildings: List,
- val requirementBuildingsEither: List,
- val requireAddon: BuildingAddonShortDto?,
- val replaceWhenDone: Boolean,
- val requirementsGlobalAddons: List?,
- val requiredTotalPop: Int?,
-)
diff --git a/src/main/kotlin/com/dowstats/data/dto/controllers/building/BuildingAddonDto.kt b/src/main/kotlin/com/dowstats/data/dto/controllers/building/BuildingAddonDto.kt
index ceab56c..af4811e 100644
--- a/src/main/kotlin/com/dowstats/data/dto/controllers/building/BuildingAddonDto.kt
+++ b/src/main/kotlin/com/dowstats/data/dto/controllers/building/BuildingAddonDto.kt
@@ -1,5 +1,8 @@
package com.dowstats.data.dto.controllers.building
+import com.dowstats.data.dto.controllers.ModifierDto
+import com.dowstats.data.dto.controllers.RequirementDto
+
data class BuildingAddonDto(
val id: Long?,
val name: String?,
@@ -11,8 +14,8 @@ data class BuildingAddonDto(
val addonCostFaith: Double?,
val addonCostSouls: Double?,
val addonCostTime: Int?,
- val addonModifiers: Set,
- val addonRequirement: AddonRequirementDto?,
+ val addonModifiers: Set,
+ val addonRequirement: RequirementDto?,
val icon: String?,
)
diff --git a/src/main/kotlin/com/dowstats/data/dto/controllers/building/BuildingFullDto.kt b/src/main/kotlin/com/dowstats/data/dto/controllers/building/BuildingFullDto.kt
index bee71ef..dd8f7d3 100644
--- a/src/main/kotlin/com/dowstats/data/dto/controllers/building/BuildingFullDto.kt
+++ b/src/main/kotlin/com/dowstats/data/dto/controllers/building/BuildingFullDto.kt
@@ -4,7 +4,8 @@ import com.dowstats.data.dto.controllers.ArmorTypeDto
import com.dowstats.data.dto.controllers.RaceDto
import com.dowstats.data.dto.controllers.UnitShortDto
import com.dowstats.data.dto.controllers.WeaponSlotDto
-import com.dowstats.data.entities.DowUnit
+import com.dowstats.data.dto.controllers.research.ResearchDto
+import com.dowstats.data.dto.controllers.research.ResearchShortDto
data class BuildingFullDto(
var id: Long?,
@@ -32,6 +33,8 @@ data class BuildingFullDto(
var icon: String?,
var modId: Long?,
var addons: Set?,
+ var researches: List?,
val units: Set,
val weapons: Set?,
+ val affectedResearches: Set,
)
diff --git a/src/main/kotlin/com/dowstats/data/dto/controllers/building/BuildingShortDto.kt b/src/main/kotlin/com/dowstats/data/dto/controllers/building/BuildingShortDto.kt
index 422dddf..edf535e 100644
--- a/src/main/kotlin/com/dowstats/data/dto/controllers/building/BuildingShortDto.kt
+++ b/src/main/kotlin/com/dowstats/data/dto/controllers/building/BuildingShortDto.kt
@@ -12,6 +12,7 @@ data class BuildingShortDto(
val name: String,
val icon: String,
val id: Long,
+ val filename: String,
val units: Set,
val armourTypeName: String,
val canDetect: Boolean,
diff --git a/src/main/kotlin/com/dowstats/data/dto/controllers/research/ResearchDto.kt b/src/main/kotlin/com/dowstats/data/dto/controllers/research/ResearchDto.kt
new file mode 100644
index 0000000..9509bc0
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/data/dto/controllers/research/ResearchDto.kt
@@ -0,0 +1,24 @@
+package com.dowstats.data.dto.controllers.research
+
+import com.dowstats.data.dto.controllers.*
+
+
+data class ResearchDto(
+ val id: Long?,
+ val name: String?,
+ val description: String?,
+ val filename: String?,
+ val costRequisition: Double?,
+ val costPower: Double?,
+ val costFaith: Double?,
+ val costSouls: Double?,
+ val costTime: Int?,
+ val modifiers: List,
+ val requirements: RequirementDto?,
+ val affectedUnits: Set,
+ val affectedSergeants: Set,
+ val affectedBuildings: Set,
+ val affectedWeapons: Set,
+ val icon: String?,
+ val modId: Long?,
+)
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/data/dto/controllers/research/ResearchShortDto.kt b/src/main/kotlin/com/dowstats/data/dto/controllers/research/ResearchShortDto.kt
new file mode 100644
index 0000000..fd52e37
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/data/dto/controllers/research/ResearchShortDto.kt
@@ -0,0 +1,8 @@
+package com.dowstats.data.dto.controllers.research
+
+data class ResearchShortDto(
+ val id: Long?,
+ val name: String?,
+ val icon: String?,
+ val buildingId: Long?,
+)
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/data/entities/AddonRequirements.kt b/src/main/kotlin/com/dowstats/data/entities/AddonRequirements.kt
deleted file mode 100644
index 0adb7a6..0000000
--- a/src/main/kotlin/com/dowstats/data/entities/AddonRequirements.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.dowstats.data.entities
-
-import com.dowstats.data.dto.controllers.building.AddonRequirementDto
-import com.fasterxml.jackson.annotation.JsonIgnore
-import jakarta.persistence.*
-
-
-@Entity
-@Table(name = "addon_requirements")
-class AddonRequirements {
-
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- var id: Long? = null
-
- @ManyToOne
- @JoinColumn(name = "addon_id", nullable = false)
- @JsonIgnore
- var addon: BuildingAddon? = null
- var reference: String? = null
- var replaceWhenDone: Boolean = false
- var value: String? = null
-
- companion object {
- val REFERENCE_REQUIREMENT_POP = "requirements\\required_total_pop.lua"
- val REFERENCE_REQUIREMENT_ADDON = "requirements\\local_required_addon.lua"
- val REFERENCE_GLOBAL_REQUIREMENT_ADDON = "requirements\\global_required_addon.lua"
- val REFERENCE_REQUIREMENT_STRUCTURE_EITHER = "requirements\\required_structure_either.lua"
- val REFERENCE_REQUIREMENT_STRUCTURE = "requirements\\required_structure.lua"
- }
-
-}
diff --git a/src/main/kotlin/com/dowstats/data/entities/Building.kt b/src/main/kotlin/com/dowstats/data/entities/Building.kt
index 95b3a7c..61c1015 100644
--- a/src/main/kotlin/com/dowstats/data/entities/Building.kt
+++ b/src/main/kotlin/com/dowstats/data/entities/Building.kt
@@ -1,10 +1,12 @@
package com.dowstats.data.entities
-import com.dowstats.data.dto.controllers.UnitShortDto
import com.dowstats.data.dto.controllers.building.BuildingAddonDto
import com.dowstats.data.dto.controllers.building.BuildingFullDto
+import com.dowstats.data.dto.controllers.research.ResearchDto
import com.dowstats.data.entities.DowUnitObject.toUnitDto
import com.dowstats.data.entities.Weapon.HardpointPosition
+import com.dowstats.data.entities.addon.BuildingAddon
+import com.dowstats.data.entities.research.Research
import jakarta.persistence.*
@@ -16,7 +18,7 @@ class Building {
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
- var canBuild: Boolean = true
+ var canBuild: Boolean? = true
@ManyToOne
@JoinColumn(name = "race_id", nullable = false)
@@ -63,10 +65,22 @@ class Building {
inverseJoinColumns = [JoinColumn(name = "unit_id")])
var units: MutableSet? = null
+ @ManyToMany
+ @JoinTable(name = "buildings_researches",
+ joinColumns = [JoinColumn(name = "building_id")],
+ inverseJoinColumns = [JoinColumn(name = "research_id")])
+ var researches: MutableSet? = null
+
+ @ManyToMany
+ @JoinTable(name = "researches_affected_buildings",
+ joinColumns = [JoinColumn(name = "building_id")],
+ inverseJoinColumns = [JoinColumn(name = "research_id")])
+ var affectedResearches: MutableSet = mutableSetOf()
+
@Transient
var weaponHardpoints: MutableSet = mutableSetOf()
- fun toDto(buildingAddons: Set?): BuildingFullDto =
+ fun toDto(buildingAddons: Set?, researches: List?): BuildingFullDto =
BuildingFullDto(
id!!,
race?.toDto(),
@@ -93,8 +107,10 @@ class Building {
icon,
modId!!,
buildingAddons,
+ researches,
units?.toList()?.toUnitDto() ?: emptySet(),
weapons?.map { it.toWeaponSlotDto() }?.toSet(),
+ affectedResearches.map { it.toResearchShortDto() }.toSet(),
)
diff --git a/src/main/kotlin/com/dowstats/data/entities/DowUnit.kt b/src/main/kotlin/com/dowstats/data/entities/DowUnit.kt
index 34d6822..68a036c 100644
--- a/src/main/kotlin/com/dowstats/data/entities/DowUnit.kt
+++ b/src/main/kotlin/com/dowstats/data/entities/DowUnit.kt
@@ -2,6 +2,7 @@ package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.UnitFullDto
import com.dowstats.data.dto.controllers.UnitShortDto
+import com.dowstats.data.entities.research.Research
import jakarta.persistence.*
@@ -30,7 +31,8 @@ class DowUnit {
var name: String? = null
var description: String? = null
- var filename: String? = null
+ var filenameSquad: String? = null
+ var filenameUnit: String? = null
var buildCostRequisition: Double? = null
var buildCostPower: Double? = null
var buildCostPopulation: Double? = null
@@ -57,11 +59,11 @@ class DowUnit {
var moveSpeed: Int? = null
var sightRadius: Int? = null
var detectRadius: Int? = null
- var reinforceCostRequisition: Int? = null
- var reinforceCostPower: Int? = null
- var reinforceCostPopulation: Int? = null
- var reinforceCostFaith: Int? = null
- var reinforceCostSouls: Int? = null
+ var reinforceCostRequisition: Double? = null
+ var reinforceCostPower: Double? = null
+ var reinforceCostPopulation: Double? = null
+ var reinforceCostFaith: Double? = null
+ var reinforceCostSouls: Double? = null
var reinforceTime: Int? = null
var maxSergeants: Int? = null
var faithIncome: Double? = null
@@ -76,6 +78,11 @@ class DowUnit {
@OneToMany(mappedBy = "unit", cascade = [CascadeType.ALL])
var weapons: MutableSet? = null
+ @ManyToMany
+ @JoinTable(name = "researches_affected_units",
+ joinColumns = [JoinColumn(name = "unit_id")],
+ inverseJoinColumns = [JoinColumn(name = "research_id")])
+ var affectedResearches: MutableSet = mutableSetOf()
fun toDto(): UnitFullDto =
@@ -86,7 +93,7 @@ class DowUnit {
armorType2?.toDto(),
name,
description,
- filename!!,
+ filenameSquad!!,
buildCostRequisition,
buildCostPower,
buildCostPopulation,
@@ -121,34 +128,24 @@ class DowUnit {
reinforceTime,
repairMax,
repairSpeed,
+ repairCostPercent,
maxSergeants,
icon,
modId!!,
sergeants?.map { it.toDto() }?.toSet(),
- weapons?.map { it.toWeaponSlotDto() }?.toSet()
+ weapons?.map { it.toWeaponSlotDto() }?.toSet(),
+ affectedResearches.map { it.toResearchShortDto() }.toSet(),
)
}
object DowUnitObject {
fun List.toUnitDto(): Set =
this.mapNotNull {
- val name = it.name ?: it.filename
+ val name = it.name ?: it.filenameSquad
val icon = it.icon
if (name == null || icon == null) null else UnitShortDto(name, icon, it.id!!,
it.armorType?.name!!,
(it.detectRadius ?: 0) > 0)
}.toSet()
- fun List.filterCompanyUnits(): List =
- this.filter {
- it.filename?.contains("_sp.") != true
- && it.filename?.contains("_sp_") != true
- && it.filename?.contains("sp_eldar_") != true
- && it.filename?.contains("_dxp3.") != true
- && it.filename?.contains("_dxp3_") != true
- && it.filename?.contains("_nis.") != true
- && it.filename?.contains("_exarch_council.") != true
- && it.filename?.contains("_dark_reapers_base.") != true
- && it.filename?.contains("tau_squad_slave_murdered") != true
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/data/entities/RequirementBase.kt b/src/main/kotlin/com/dowstats/data/entities/RequirementBase.kt
new file mode 100644
index 0000000..cff0dd1
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/data/entities/RequirementBase.kt
@@ -0,0 +1,16 @@
+package com.dowstats.data.entities
+
+import jakarta.persistence.GeneratedValue
+import jakarta.persistence.GenerationType
+import jakarta.persistence.Id
+import jakarta.persistence.MappedSuperclass
+
+@MappedSuperclass
+open class RequirementBase {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ var id: Long? = null
+
+ var reference: String? = null
+ var value: String? = null
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/data/entities/Sergant.kt b/src/main/kotlin/com/dowstats/data/entities/Sergant.kt
index e5c09d4..2eda976 100644
--- a/src/main/kotlin/com/dowstats/data/entities/Sergant.kt
+++ b/src/main/kotlin/com/dowstats/data/entities/Sergant.kt
@@ -2,6 +2,7 @@ package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.SergeantDto
import com.dowstats.data.entities.Weapon.HardpointPosition
+import com.dowstats.data.entities.research.Research
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.*
@@ -29,7 +30,7 @@ class Sergeant {
var name: String? = null
var description: String? = null
- var filename: String? = null
+ var filename: String = ""
var buildCostRequisition: Double? = null
var buildCostPower: Double? = null
var buildCostPopulation: Double? = null
@@ -49,6 +50,8 @@ class Sergeant {
var powerIncome: Double? = null
var requisitionIncome: Double? = null
+ var modId: Long? = null
+
@Transient
var weaponHardpoints: MutableSet = mutableSetOf()
@@ -56,6 +59,12 @@ class Sergeant {
@OneToMany(mappedBy = "sergeant", cascade = [CascadeType.ALL])
var weapons: MutableSet? = null
+ @ManyToMany
+ @JoinTable(name = "researches_affected_sergeants",
+ joinColumns = [JoinColumn(name = "sergeant_id")],
+ inverseJoinColumns = [JoinColumn(name = "research_id")])
+ var affectedResearches: MutableSet = mutableSetOf()
+
fun toDto(): SergeantDto =
SergeantDto(
id!!,
@@ -82,6 +91,7 @@ class Sergeant {
sightRadius,
detectRadius,
icon,
- weapons?.map { it.toWeaponSlotDto() }
+ weapons?.map { it.toWeaponSlotDto() },
+ affectedResearches.map { it.toResearchShortDto() }.toSet()
)
}
diff --git a/src/main/kotlin/com/dowstats/data/entities/Weapon.kt b/src/main/kotlin/com/dowstats/data/entities/Weapon.kt
index 9fa9dda..2c2b4bd 100644
--- a/src/main/kotlin/com/dowstats/data/entities/Weapon.kt
+++ b/src/main/kotlin/com/dowstats/data/entities/Weapon.kt
@@ -1,6 +1,7 @@
package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.WeaponDto
+import com.dowstats.data.entities.research.Research
import jakarta.persistence.*
@@ -14,8 +15,8 @@ class Weapon {
var filename: String? = null
var name: String? = null
var description: String? = null
- var costRequisition: Int? = null
- var costPower: Int? = null
+ var costRequisition: Double? = null
+ var costPower: Double? = null
var costTimeSeconds: Int? = null
var accuracy: Double? = null
var reloadTime: Double? = null
@@ -37,6 +38,21 @@ class Weapon {
var haveEquipButton: Boolean = true
var modId: Long? = null
+ @ManyToMany
+ @JoinTable(name = "researches_affected_weapons",
+ joinColumns = [JoinColumn(name = "weapon_id")],
+ inverseJoinColumns = [JoinColumn(name = "research_id")])
+ var affectedResearches: MutableSet = mutableSetOf()
+
+ @OneToMany(mappedBy = "weapon", cascade = [CascadeType.ALL])
+ var unitsUse: MutableSet? = null
+
+ @OneToMany(mappedBy = "weapon", cascade = [CascadeType.ALL])
+ var sergeantsUse: MutableSet? = null
+
+ @OneToMany(mappedBy = "weapon", cascade = [CascadeType.ALL])
+ var buildingUse: MutableSet? = null
+
// for many-to-many persistance
data class HardpointPosition(val weaponId: Long, val hardpoint: Int, val order: Int)
@@ -71,6 +87,7 @@ class Weapon {
icon,
haveEquipButton,
modId,
- weaponPiercings.map { it.toDto() }
+ weaponPiercings.map { it.toDto() },
+ affectedResearches.map { it.toResearchShortDto() }.toSet(),
)
}
diff --git a/src/main/kotlin/com/dowstats/data/entities/AddonModifiers.kt b/src/main/kotlin/com/dowstats/data/entities/addon/AddonModifiers.kt
similarity index 74%
rename from src/main/kotlin/com/dowstats/data/entities/AddonModifiers.kt
rename to src/main/kotlin/com/dowstats/data/entities/addon/AddonModifiers.kt
index 8610c41..ceca423 100644
--- a/src/main/kotlin/com/dowstats/data/entities/AddonModifiers.kt
+++ b/src/main/kotlin/com/dowstats/data/entities/addon/AddonModifiers.kt
@@ -1,6 +1,6 @@
-package com.dowstats.data.entities
+package com.dowstats.data.entities.addon
-import com.dowstats.data.dto.controllers.building.AddonModifierDto
+import com.dowstats.data.dto.controllers.ModifierDto
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.*
@@ -22,12 +22,12 @@ class AddonModifiers {
var usageType: String? = null
var value: Double? = null
- fun toDto(): AddonModifierDto {
- return AddonModifierDto(
+ fun toDto(): ModifierDto {
+ return ModifierDto(
id = id!!,
reference = reference,
usageType = usageType,
- value = value
+ value = value,
)
}
}
diff --git a/src/main/kotlin/com/dowstats/data/entities/addon/AddonRequirements.kt b/src/main/kotlin/com/dowstats/data/entities/addon/AddonRequirements.kt
new file mode 100644
index 0000000..64da8cc
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/data/entities/addon/AddonRequirements.kt
@@ -0,0 +1,17 @@
+package com.dowstats.data.entities.addon
+
+import com.dowstats.data.entities.RequirementBase
+import com.fasterxml.jackson.annotation.JsonIgnore
+import jakarta.persistence.*
+
+
+@Entity
+@Table(name = "addon_requirements")
+class AddonRequirements: RequirementBase() {
+
+ @ManyToOne
+ @JoinColumn(name = "addon_id", nullable = false)
+ @JsonIgnore
+ var addon: BuildingAddon? = null
+ var replaceWhenDone: Boolean = false
+}
diff --git a/src/main/kotlin/com/dowstats/data/entities/BuildingAddon.kt b/src/main/kotlin/com/dowstats/data/entities/addon/BuildingAddon.kt
similarity index 89%
rename from src/main/kotlin/com/dowstats/data/entities/BuildingAddon.kt
rename to src/main/kotlin/com/dowstats/data/entities/addon/BuildingAddon.kt
index 2bd0c28..b4beeeb 100644
--- a/src/main/kotlin/com/dowstats/data/entities/BuildingAddon.kt
+++ b/src/main/kotlin/com/dowstats/data/entities/addon/BuildingAddon.kt
@@ -1,8 +1,9 @@
-package com.dowstats.data.entities
+package com.dowstats.data.entities.addon
-import com.dowstats.data.dto.controllers.building.AddonRequirementDto
+import com.dowstats.data.dto.controllers.RequirementDto
import com.dowstats.data.dto.controllers.building.BuildingAddonDto
import com.dowstats.data.dto.controllers.building.BuildingAddonShortDto
+import com.dowstats.data.entities.Building
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.*
@@ -39,7 +40,7 @@ class BuildingAddon {
var icon: String? = null
var modId: Long? = null
- fun toDto(addonRequirementDto: AddonRequirementDto?): BuildingAddonDto = BuildingAddonDto(
+ fun toDto(addonRequirementDto: RequirementDto?): BuildingAddonDto = BuildingAddonDto(
id = id,
name = name,
description = description,
diff --git a/src/main/kotlin/com/dowstats/data/entities/research/Research.kt b/src/main/kotlin/com/dowstats/data/entities/research/Research.kt
new file mode 100644
index 0000000..2098a60
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/data/entities/research/Research.kt
@@ -0,0 +1,137 @@
+package com.dowstats.data.entities.research
+
+import com.dowstats.data.dto.controllers.EntityCompressDtoObject.compressDto
+import com.dowstats.data.dto.controllers.ModifierDto
+import com.dowstats.data.dto.controllers.RequirementDto
+import com.dowstats.data.dto.controllers.SergeantUnitShortDto
+import com.dowstats.data.dto.controllers.WeaponUnitShortDto
+import com.dowstats.data.dto.controllers.research.ResearchDto
+import com.dowstats.data.dto.controllers.research.ResearchShortDto
+import com.dowstats.data.entities.Building
+import com.dowstats.data.entities.DowUnit
+import com.dowstats.data.entities.Sergeant
+import com.dowstats.data.entities.Weapon
+import jakarta.persistence.*
+
+
+@Entity
+@Table(name = "researches")
+class Research {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ var id: Long? = null
+
+ var name: String? = null
+ var description: String? = null
+ var filename: String? = null
+ var costRequisition: Double? = null
+ var costPower: Double? = null
+ var costFaith: Double? = null
+ var costSouls: Double? = null
+ var costTime: Int? = null
+ var icon: String? = null
+ var modId: Long? = null
+
+ @OneToMany(mappedBy = "research", cascade = [CascadeType.ALL])
+ var researchModifiers: MutableSet = mutableSetOf()
+
+ @OneToMany(mappedBy = "research", cascade = [CascadeType.ALL])
+ var addonRequirements: MutableSet = mutableSetOf()
+
+ @ManyToMany
+ @JoinTable(name = "researches_affected_units",
+ joinColumns = [JoinColumn(name = "research_id")],
+ inverseJoinColumns = [JoinColumn(name = "unit_id")])
+ var affectedUnits: MutableSet = mutableSetOf()
+
+ @ManyToMany
+ @JoinTable(name = "researches_affected_sergeants",
+ joinColumns = [JoinColumn(name = "research_id")],
+ inverseJoinColumns = [JoinColumn(name = "sergeant_id")])
+ var affectedSergeants: MutableSet = mutableSetOf()
+
+ @ManyToMany
+ @JoinTable(name = "researches_affected_buildings",
+ joinColumns = [JoinColumn(name = "research_id")],
+ inverseJoinColumns = [JoinColumn(name = "building_id")])
+ var affectedBuildings: MutableSet = mutableSetOf()
+
+ @ManyToMany
+ @JoinTable(name = "researches_affected_weapons",
+ joinColumns = [JoinColumn(name = "research_id")],
+ inverseJoinColumns = [JoinColumn(name = "weapon_id")])
+ var affectedWeapons: MutableSet = mutableSetOf()
+
+ @ManyToMany
+ @JoinTable(name = "buildings_researches",
+ joinColumns = [JoinColumn(name = "research_id")],
+ inverseJoinColumns = [JoinColumn(name = "building_id")])
+ var buildings: MutableSet? = null
+
+ fun toResearchShortDto(): ResearchShortDto = ResearchShortDto(
+ id = id!!,
+ name = name,
+ icon = icon,
+ buildings?.firstOrNull()?.id
+ )
+
+ fun toResearchDto(requirements: RequirementDto?): ResearchDto = ResearchDto(
+ id = id!!,
+ name = name,
+ icon = icon,
+ filename = filename,
+ description = description,
+ costRequisition = costRequisition,
+ costPower = costPower,
+ costFaith = costFaith,
+ costSouls = costSouls,
+ costTime = costTime,
+ modifiers = researchModifiers.map {
+ ModifierDto(
+ it.id!!,
+ it.reference,
+ it.usageType,
+ it.value,
+ it.target,
+ )
+ }.sortedBy { it.target },
+ requirements = requirements,
+ affectedUnits = affectedUnits.map { it.compressDto() }.toSet(),
+ affectedSergeants = affectedSergeants.map {
+ SergeantUnitShortDto(
+ it.id!!,
+ it.filename!!,
+ it.name,
+ it.icon,
+ it.unit!!.compressDto()
+ )
+ }.toSet(),
+ affectedBuildings = affectedBuildings.map { it.compressDto() }.toSet(),
+ affectedWeapons = affectedWeapons.mapNotNull {
+ if(it.unitsUse!!.isEmpty() && it.sergeantsUse!!.isEmpty() && it.buildingUse!!.isEmpty()) {
+ null
+ } else
+ WeaponUnitShortDto(
+ it.id!!,
+ it.filename!!,
+ it.name,
+ it.unitsUse?.mapNotNull {
+ it.unit?.compressDto()
+ }?.toSet() ?: emptySet(),
+ it.sergeantsUse?.map {
+ SergeantUnitShortDto(
+ it.sergeant!!.id!!,
+ it.sergeant!!.filename!!,
+ it.sergeant!!.name,
+ it.sergeant!!.icon,
+ it.sergeant!!.unit!!.compressDto()
+ )
+ }?.toSet() ?: emptySet(),
+ it.buildingUse?.map { it.building!!.compressDto() }?.toSet() ?: emptySet()
+ )
+ }.toSet(),
+ modId = modId,
+ )
+
+}
diff --git a/src/main/kotlin/com/dowstats/data/entities/research/ResearchModifiers.kt b/src/main/kotlin/com/dowstats/data/entities/research/ResearchModifiers.kt
new file mode 100644
index 0000000..99928bb
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/data/entities/research/ResearchModifiers.kt
@@ -0,0 +1,35 @@
+package com.dowstats.data.entities.research
+
+import com.dowstats.data.dto.controllers.ModifierDto
+import com.fasterxml.jackson.annotation.JsonIgnore
+import jakarta.persistence.*
+
+
+@Entity
+@Table(name = "research_modifiers")
+class ResearchModifiers {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ var id: Long? = null
+
+ @ManyToOne
+ @JoinColumn(name = "research_id", nullable = false)
+ @JsonIgnore
+ var research: Research? = null
+
+ var reference: String? = null
+ var target: String? = null
+ var usageType: String? = null
+ var value: Double? = null
+
+ fun toDto(): ModifierDto {
+ return ModifierDto(
+ id = id!!,
+ reference = reference,
+ usageType = usageType,
+ value = value,
+ target = target,
+ )
+ }
+}
diff --git a/src/main/kotlin/com/dowstats/data/entities/research/ResearchRequirements.kt b/src/main/kotlin/com/dowstats/data/entities/research/ResearchRequirements.kt
new file mode 100644
index 0000000..76b2a4e
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/data/entities/research/ResearchRequirements.kt
@@ -0,0 +1,16 @@
+package com.dowstats.data.entities.research
+
+import com.dowstats.data.entities.RequirementBase
+import com.fasterxml.jackson.annotation.JsonIgnore
+import jakarta.persistence.*
+
+
+@Entity
+@Table(name = "research_requirements")
+class ResearchRequirements : RequirementBase() {
+
+ @ManyToOne
+ @JoinColumn(name = "research_id", nullable = false)
+ @JsonIgnore
+ var research: Research? = null
+}
diff --git a/src/main/kotlin/com/dowstats/data/repositories/AddonRepository.kt b/src/main/kotlin/com/dowstats/data/repositories/AddonRepository.kt
index 9c9749e..fd60691 100644
--- a/src/main/kotlin/com/dowstats/data/repositories/AddonRepository.kt
+++ b/src/main/kotlin/com/dowstats/data/repositories/AddonRepository.kt
@@ -1,10 +1,6 @@
package com.dowstats.data.repositories
-import com.dowstats.data.entities.Building
-import com.dowstats.data.entities.BuildingAddon
-import com.dowstats.data.entities.DowUnit
-import com.dowstats.data.entities.Race
-import org.springframework.data.jpa.repository.Query
+import com.dowstats.data.entities.addon.BuildingAddon
import org.springframework.data.repository.CrudRepository
interface AddonRepository : CrudRepository{
diff --git a/src/main/kotlin/com/dowstats/data/repositories/ModRepository.kt b/src/main/kotlin/com/dowstats/data/repositories/ModRepository.kt
index 6e868a3..2b819fd 100644
--- a/src/main/kotlin/com/dowstats/data/repositories/ModRepository.kt
+++ b/src/main/kotlin/com/dowstats/data/repositories/ModRepository.kt
@@ -13,4 +13,10 @@ interface ModRepository : CrudRepository{
""", nativeQuery = true)
@Modifying
fun clearModData(modId: Long)
+
+ @Query("""
+ CALL delete_campaign_entities(:modId)
+ """, nativeQuery = true)
+ @Modifying
+ fun removeCampaignEntities(modId: Long)
}
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/data/repositories/ResearchRepository.kt b/src/main/kotlin/com/dowstats/data/repositories/ResearchRepository.kt
new file mode 100644
index 0000000..b1f851b
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/data/repositories/ResearchRepository.kt
@@ -0,0 +1,13 @@
+package com.dowstats.data.repositories
+
+import com.dowstats.data.entities.DowUnit
+import com.dowstats.data.entities.Weapon
+import com.dowstats.data.entities.addon.BuildingAddon
+import com.dowstats.data.entities.research.Research
+import org.springframework.data.repository.*
+
+interface ResearchRepository : CrudRepository{
+ fun deleteAllByModId(modId: Long)
+ fun findAllByModId(modId: Long): List
+ fun findFirstByModIdAndFilename(modId: Long, fileName: String): Research?
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/data/repositories/SergeantRepository.kt b/src/main/kotlin/com/dowstats/data/repositories/SergeantRepository.kt
index 7608640..663b02c 100644
--- a/src/main/kotlin/com/dowstats/data/repositories/SergeantRepository.kt
+++ b/src/main/kotlin/com/dowstats/data/repositories/SergeantRepository.kt
@@ -1,6 +1,9 @@
package com.dowstats.data.repositories
import com.dowstats.data.entities.Sergeant
+import com.dowstats.data.entities.Weapon
import org.springframework.data.repository.CrudRepository
-interface SergeantRepository : CrudRepository
\ No newline at end of file
+interface SergeantRepository : CrudRepository{
+ fun findAllByModId(modId: Long): List
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/data/repositories/UnitRepository.kt b/src/main/kotlin/com/dowstats/data/repositories/UnitRepository.kt
index 490ecc7..e66a350 100644
--- a/src/main/kotlin/com/dowstats/data/repositories/UnitRepository.kt
+++ b/src/main/kotlin/com/dowstats/data/repositories/UnitRepository.kt
@@ -18,7 +18,5 @@ interface UnitRepository : CrudRepository {
""")
fun findByModIdAndRace(modId: Long, race: Race?): List
- fun findByFilenameAndRaceAndModId(fileName: String, race: Race, modId: Long): DowUnit?
-
fun deleteAllByModIdAndRaceId(modId: Long, raceId: String)
}
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/data/repositories/WeaponRepository.kt b/src/main/kotlin/com/dowstats/data/repositories/WeaponRepository.kt
index 7cd68fc..f205c0f 100644
--- a/src/main/kotlin/com/dowstats/data/repositories/WeaponRepository.kt
+++ b/src/main/kotlin/com/dowstats/data/repositories/WeaponRepository.kt
@@ -2,8 +2,10 @@ package com.dowstats.data.repositories
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.Weapon
+import com.dowstats.data.entities.research.Research
import org.springframework.data.repository.*
interface WeaponRepository : CrudRepository{
fun deleteAllByModId(modId: Long)
+ fun findAllByModId(modId: Long): List
}
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/service/datamaps/CommonMapping.kt b/src/main/kotlin/com/dowstats/service/datamaps/CommonMapping.kt
new file mode 100644
index 0000000..0c8aa74
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/service/datamaps/CommonMapping.kt
@@ -0,0 +1,44 @@
+package com.dowstats.service.datamaps
+
+import com.dowstats.data.dto.controllers.building.BuildingShortDto
+import com.dowstats.data.entities.Building
+import com.dowstats.data.entities.DowUnitObject.toUnitDto
+
+object CommonMapping {
+ fun List.toBuildingShortDto(): List =
+ this
+ .sortedWith(compareBy { it.units?.isEmpty() }.thenBy{ it.buildCostRequisition?.let { 0 - it } })
+ .mapNotNull {
+ val name = it.name ?: it.filename?.replace(".rgd", "")?.replace("_", " ")
+ val icon = it.icon
+ if (name == null || icon == null) null else BuildingShortDto(
+ name, icon, it.id!!,
+ it.filename!!,
+ it.units?.toList()?.toUnitDto() ?: emptySet(),
+ it.armorType?.name!!,
+ (it.detectRadius ?: 0) > 0
+ )
+ }
+
+ fun isNotCompanyEntity(fileName: String): Boolean =
+ !fileName.contains("_dxp3.") &&
+ !fileName.contains("_dxp3_") &&
+ !fileName.contains("sp_eldar_") &&
+ !fileName.contains("_sp_") &&
+ !fileName.contains("_sp.") &&
+ !fileName.contains("_nis.") &&
+ !fileName.contains("_interface_relay.") &&
+ !fileName.contains("necron_tunnel.rgd") &&
+ !fileName.contains("_exarch_council.") &&
+ !fileName.contains("_dark_reapers_base.") &&
+ !fileName.contains("eldar_deep_strike_building.rgd") &&
+ !fileName.contains("ork_deep_strike_building.rgd") &&
+ !fileName.contains("_caravel_ai.rgd") &&
+ !fileName.contains("sisters_tanktrap_ai.rgd") &&
+ !fileName.contains("sisters_hq_ktgm.rgd") &&
+ !fileName.contains("tau_squad_slave_murdered") &&
+ !fileName.contains("single_player_only") &&
+ !fileName.contains("space_marine_drop_pod_building.rgd")
+
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/service/datamaps/DowBuildingMappingService.kt b/src/main/kotlin/com/dowstats/service/datamaps/DowBuildingMappingService.kt
index 782417a..6b14acd 100644
--- a/src/main/kotlin/com/dowstats/service/datamaps/DowBuildingMappingService.kt
+++ b/src/main/kotlin/com/dowstats/service/datamaps/DowBuildingMappingService.kt
@@ -1,147 +1,68 @@
package com.dowstats.service.datamaps
-import com.dowstats.data.dto.controllers.building.AddonRequirementDto
+import com.dowstats.Metadata.Requirements
import com.dowstats.data.dto.controllers.building.BuildingFullDto
-import com.dowstats.data.dto.controllers.building.BuildingShortDto
import com.dowstats.data.dto.controllers.building.RaceBuildings
-import com.dowstats.data.entities.AddonRequirements
import com.dowstats.data.entities.Building
-import com.dowstats.data.entities.DowUnitObject.filterCompanyUnits
-import com.dowstats.data.entities.DowUnitObject.toUnitDto
-import com.dowstats.data.repositories.AddonRepository
import com.dowstats.data.repositories.BuildingRepository
import com.dowstats.data.repositories.RaceRepository
+import com.dowstats.service.datamaps.CommonMapping.isNotCompanyEntity
+import com.dowstats.service.datamaps.CommonMapping.toBuildingShortDto
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
@Service
class DowBuildingMappingService @Autowired constructor(
val buildingRepository: BuildingRepository,
- val addonRepository: AddonRepository,
+ val requirementsMappingComponent: RequirementsMappingComponent,
val raceRepository: RaceRepository
) {
fun findBuildingsByMod(modId: Long): List {
return getAllBuildings(modId).groupBy { it.race }.mapNotNull { raceUnits ->
- RaceBuildings(raceUnits.key?.toDto() ?: throw Exception("Race is null"), raceUnits.value.toBuildingDto())
+ RaceBuildings(raceUnits.key?.toDto() ?: throw Exception("Race is null"), raceUnits.value.toBuildingShortDto())
}
}
fun findBuildingsByModAndRace(modId: Long, race: String): RaceBuildings {
val buildings = getAllBuildings(modId, race)
val raceEntity = race.let { raceRepository.findById(race) ?: throw Exception("Race $race not found") }
- return RaceBuildings(raceEntity.toDto(), buildings.toBuildingDto())
+ return RaceBuildings(raceEntity.toDto(), buildings.toBuildingShortDto())
}
fun mapToDto(building: Building): BuildingFullDto {
val buildingAddons = building.addons?.map { addon ->
- val requirements = addon.addonRequirements
-
- val requireCap =
- requirements?.find { it.reference == AddonRequirements.REFERENCE_REQUIREMENT_POP }?.value?.toDouble()
- ?.toInt()
-
- val requirementAddon =
- requirements?.find { it.reference == AddonRequirements.REFERENCE_REQUIREMENT_ADDON }?.value?.let {
- building.addons?.find { addon -> addon.filename == it.split("\\").last().replace(".lua", ".rgd") }
- }
-
- val replaceWhenDone = requirements?.find { it.reference == AddonRequirements.REFERENCE_REQUIREMENT_ADDON }?.replaceWhenDone ?: false
-
- val requirementAddonGlobal =
- requirements?.filter { it.reference == AddonRequirements.REFERENCE_GLOBAL_REQUIREMENT_ADDON }
- ?.mapNotNull { rgra ->
- val addonFileName = rgra.value?.split("\\")?.last()?.replace(".lua", ".rgd")
- addonFileName?.let {
- addonRepository.findFirstByModIdAndFilename(
- building.modId!!,
- it.split("\\").last().replace(".lua", ".rgd")
- )?.toShortDto()
- }
- }
-
- val requirementBuildings =
- requirements?.filter { it.reference == AddonRequirements.REFERENCE_REQUIREMENT_STRUCTURE }?.mapNotNull {
- val buildingFileName = it.value?.split("\\")?.last()?.replace(".lua", ".rgd")
- buildingFileName?.let {
- buildingRepository.findByModIdAndFilename(building.modId!!, buildingFileName)
- }
- }?.filter { it.id != building.id }?.distinct()?.toBuildingDto()
-
- val requirementBuildingsEither =
- requirements?.find { it.reference == AddonRequirements.REFERENCE_REQUIREMENT_STRUCTURE_EITHER }?.let {
- it.value?.split(";")?.mapNotNull { bPath ->
- buildingRepository.findByModIdAndFilename(
- building.modId!!,
- bPath.split("\\").last().replace(".lua", ".rgd")
- )
- }
- }?.toBuildingDto()
-
- val addonRequirement = if (requireCap != null ||
- requirementAddon != null ||
- (requirementBuildings?.size ?: 0) > 0 ||
- (requirementBuildingsEither?.size ?: 0) > 0 ||
- (requirementAddonGlobal?.size ?: 0) > 0
- ) {
- AddonRequirementDto(
- requirementBuildings ?: emptyList(),
- requirementBuildingsEither ?: emptyList(),
- requirementAddon?.toShortDto(),
- replaceWhenDone,
- requirementAddonGlobal,
- requireCap
+ val replaceWhenDone = addon.addonRequirements?.find { it.reference == Requirements.REFERENCE_REQUIREMENT_ADDON }?.replaceWhenDone ?: false
+ val requirement = requirementsMappingComponent
+ .getRequirements(addon.addonRequirements?.toList() ?: emptyList(),
+ building.modId!!,
+ building.addons?.toList() ?: emptyList()
)
- } else null
- addon.toDto(addonRequirement)
+ addon.toDto(requirement?.copy(
+ replaceWhenDone = replaceWhenDone,
+ requirementBuildings = requirement.requirementBuildings.filter { it.id != building.id }.toSet())
+ )
}?.sortedBy { it.name }?.toSet()
- return building.toDto(buildingAddons)
+ val researches = building.researches?.map {research ->
+ val requiremens = requirementsMappingComponent
+ .getRequirements(research.addonRequirements.toList() ?: emptyList(),
+ building.modId!!,
+ building.addons?.toList() ?: emptyList()
+ )
+ research.toResearchDto(requiremens)
+ }?.sortedBy { it.name }
+
+ return building.toDto(buildingAddons, researches)
}
- private fun List.toBuildingDto(): List =
- this
- .sortedWith(compareBy { it.units?.isEmpty() }.thenBy{ it.buildCostRequisition?.let { 0 - it } })
- .mapNotNull {
- val name = it.name ?: it.filename?.replace(".rgd", "")?.replace("_", " ")
- val icon = it.icon
- if (name == null || icon == null) null else BuildingShortDto(
- name, icon, it.id!!,
- it.units?.toList()?.filterCompanyUnits()?.toUnitDto() ?: emptySet(),
- it.armorType?.name!!,
- (it.detectRadius ?: 0) > 0
- )
- }
-
-
private fun getAllBuildings(modId: Long, race: String? = null): List {
val raceEntity = race?.let { raceRepository.findById(race) ?: throw Exception("Race $race not found") }
- return filterCompanyUnits(buildingRepository.findByModIdAndRace(modId, raceEntity))
+ return buildingRepository.findByModIdAndRace(modId, raceEntity)
}
- private fun filterCompanyUnits(buildings: List): List =
- buildings.filter {
- it.filename?.contains("_sp.") != true
- && it.filename?.contains("_sp_") != true
- && it.filename?.contains("sp_eldar_") != true
- && it.filename?.contains("_dxp3.") != true
- && it.filename?.contains("_dxp3_") != true
- && it.filename?.contains("_nis.") != true
- && it.filename?.contains("_interface_relay.") != true
- && it.filename?.contains("necron_tunnel.rgd") != true
- && it.filename?.contains("_exarch_council.") != true
- && it.filename?.contains("_dark_reapers_base.") != true
- && it.filename?.contains("eldar_deep_strike_building.rgd") != true
- && it.filename?.contains("ork_deep_strike_building.rgd") != true
- && it.filename?.contains("_caravel_ai.rgd") != true
- && it.filename?.contains("sisters_tanktrap_ai.rgd") != true
- && it.filename?.contains("sisters_hq_ktgm.rgd") != true
- && it.filename?.contains("tau_squad_slave_murdered") != true
- && it.filename?.contains("single_player_only") != true
- && it.filename?.contains("space_marine_drop_pod_building.rgd") != true
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/service/datamaps/DowUnitMappingService.kt b/src/main/kotlin/com/dowstats/service/datamaps/DowUnitMappingService.kt
index a460512..9f51043 100644
--- a/src/main/kotlin/com/dowstats/service/datamaps/DowUnitMappingService.kt
+++ b/src/main/kotlin/com/dowstats/service/datamaps/DowUnitMappingService.kt
@@ -1,9 +1,7 @@
package com.dowstats.service.datamaps
import com.dowstats.data.dto.controllers.RaceUnits
-import com.dowstats.data.dto.controllers.UnitShortDto
import com.dowstats.data.entities.DowUnit
-import com.dowstats.data.entities.DowUnitObject.filterCompanyUnits
import com.dowstats.data.entities.DowUnitObject.toUnitDto
import com.dowstats.data.entities.Race
import com.dowstats.data.repositories.RaceRepository
@@ -40,7 +38,7 @@ class DowUnitMappingService @Autowired constructor(
.toUnitDto()
val support = units.filter {
- it.capInfantry?.let { it == 0 } ?: false && it.reinforceCostPopulation?.let { it == 0 } ?: true &&
+ it.capInfantry?.let { it == 0 } ?: false && it.reinforceCostPopulation?.let { it == 0.0 } ?: true &&
it.capSupport?.let { it == 0 } ?: false
}
.toUnitDto()
@@ -51,7 +49,7 @@ class DowUnitMappingService @Autowired constructor(
private fun getAllUnits(modId: Long, race: String? = null): List {
val raceEntity = race?.let{ raceRepository.findById(race) ?: throw Exception("Race $race not found") }
- return unitRepository.findByModIdAndRace(modId, raceEntity).filterCompanyUnits()
+ return unitRepository.findByModIdAndRace(modId, raceEntity)
}
}
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/service/datamaps/RequirementsMappingComponent.kt b/src/main/kotlin/com/dowstats/service/datamaps/RequirementsMappingComponent.kt
new file mode 100644
index 0000000..bc9b12f
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/service/datamaps/RequirementsMappingComponent.kt
@@ -0,0 +1,94 @@
+package com.dowstats.service.datamaps
+
+import com.dowstats.Metadata.Requirements
+import com.dowstats.data.dto.controllers.RequirementDto
+import com.dowstats.data.dto.controllers.RequirementResearchDto
+import com.dowstats.data.entities.RequirementBase
+import com.dowstats.data.entities.addon.BuildingAddon
+import com.dowstats.data.repositories.AddonRepository
+import com.dowstats.data.repositories.BuildingRepository
+import com.dowstats.data.repositories.ResearchRepository
+import com.dowstats.service.datamaps.CommonMapping.toBuildingShortDto
+import org.springframework.stereotype.Component
+
+@Component
+class RequirementsMappingComponent(
+ val addonRepository: AddonRepository,
+ val buildingRepository: BuildingRepository,
+ val researchRepository: ResearchRepository,
+) {
+ fun getRequirements(requirements : List, modId: Long, thisBuildingAddons: List = emptyList()) : RequirementDto? {
+
+ val requireCap =
+ requirements.find { it.reference == Requirements.REFERENCE_REQUIREMENT_POP }?.value?.toDouble()
+ ?.toInt()
+
+ val requirementAddon =
+ requirements.find { it.reference == Requirements.REFERENCE_REQUIREMENT_ADDON }?.value?.let {
+ thisBuildingAddons.find { addon -> addon.filename == it.split("\\").last().replace(".lua", ".rgd") }
+ }?.toShortDto()
+
+
+ val requirementAddonGlobal =
+ requirements.filter { it.reference == Requirements.REFERENCE_GLOBAL_REQUIREMENT_ADDON }
+ .mapNotNull { rgra ->
+ val addonFileName = rgra.value?.split("\\")?.last()?.replace(".lua", ".rgd")
+ addonFileName?.let {
+ addonRepository.findFirstByModIdAndFilename(
+ modId,
+ it.split("\\").last().replace(".lua", ".rgd")
+ )?.toShortDto()
+ }
+ }.toSet()
+
+ val requirementBuildings =
+ requirements.filter { it.reference == Requirements.REFERENCE_REQUIREMENT_STRUCTURE }.mapNotNull {
+ val buildingFileName = it.value?.split("\\")?.last()?.replace(".lua", ".rgd")
+ buildingFileName?.let {
+ buildingRepository.findByModIdAndFilename(modId, buildingFileName)
+ }
+ }.distinct().toBuildingShortDto().toSet()
+
+ val requirementBuildingsEither =
+ requirements.find { it.reference == Requirements.REFERENCE_REQUIREMENT_STRUCTURE_EITHER }?.let {
+ it.value?.split(";")?.mapNotNull { bPath ->
+ buildingRepository.findByModIdAndFilename(
+ modId,
+ bPath.split("\\").last().replace(".lua", ".rgd")
+ )
+ }
+ }?.toBuildingShortDto()?.toSet() ?: emptySet()
+
+ val requirementResearches =
+ requirements.filter { it.reference == Requirements.REFERENCE_REQUIREMENT_RESEARCH }.mapNotNull {
+ val research = it.value?.split(";")?.first()
+ val mustNotBeCompleteStr = it.value?.split(";")?.last()
+ val researchFileName = research?.split("\\")?.last()?.replace(".lua", ".rgd")?.let {
+ if(it.endsWith(".rgd")) it else "$it.rgd"
+ }
+ researchFileName?.let {
+ researchRepository.findFirstByModIdAndFilename(modId, researchFileName)
+ }?.toResearchShortDto()?.let {
+ val mustNotBeComplete = mustNotBeCompleteStr == "true"
+ RequirementResearchDto(it, mustNotBeComplete)
+ }
+ }.toSet()
+
+ return if (requireCap != null ||
+ requirementAddon != null ||
+ requirementBuildings.isNotEmpty() ||
+ requirementBuildingsEither.isNotEmpty() ||
+ requirementResearches.isNotEmpty() ||
+ requirementAddonGlobal.isNotEmpty()
+ ) {
+ RequirementDto(
+ requirementBuildings,
+ requirementBuildingsEither,
+ requirementResearches,
+ requirementAddon,
+ requirementAddonGlobal,
+ requireCap
+ )
+ } else null
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/dowstats/service/postparsing/PostParsingService.kt b/src/main/kotlin/com/dowstats/service/postparsing/PostParsingService.kt
new file mode 100644
index 0000000..ea73ef3
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/service/postparsing/PostParsingService.kt
@@ -0,0 +1,107 @@
+package com.dowstats.service.postparsing
+
+import com.dowstats.configuration.StorageConfig
+import com.dowstats.data.entities.*
+import com.dowstats.data.entities.research.Research
+import com.dowstats.data.repositories.*
+import org.slf4j.LoggerFactory
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.stereotype.Service
+import java.awt.image.BufferedImage
+import java.io.File
+import java.nio.file.Path
+import javax.imageio.ImageIO
+import kotlin.io.path.exists
+
+
+@Service
+class PostParsingService @Autowired constructor(
+ val researchRepository: ResearchRepository,
+ val unitRepository: UnitRepository,
+ val sergeantRepository: SergeantRepository,
+ val buildingRepository: BuildingRepository,
+ val weaponRepository: WeaponRepository,
+) {
+
+ val log = LoggerFactory.getLogger(PostParsingService::class.java)
+
+ fun bindResearch(mod: Mod) {
+ try {
+ val modId = mod.id!!
+ val researches = researchRepository.findAllByModId(modId)
+ val units = unitRepository.findByModIdAndRace(modId, null)
+ val sergeants = sergeantRepository.findAllByModId(modId)
+ val buildings = buildingRepository.findByModIdAndRace(modId, null)
+ val weapons = weaponRepository.findAllByModId(modId)
+
+ bindResearchUnits(units, researches)
+ bindResearchSergeants(sergeants, researches)
+ bindResearchBuildings(buildings, researches)
+ bindResearchWeapons(weapons, researches)
+
+ } catch (e: Exception) {
+ log.warn("Error occurred during bind researches", e)
+ }
+
+ }
+
+ private fun bindResearchUnits(units: List, researches: List) {
+
+ val unitsWithBindings: List = researches.flatMap { research ->
+ research.researchModifiers.mapNotNull { modifier ->
+ units.find {
+ it.filenameSquad?.replace(".rgd", "") == modifier.target ||
+ it.filenameUnit?.replace(".rgd", "") == modifier.target
+ }
+ ?.let {
+ it.affectedResearches.add(research)
+ it
+ }
+ }
+ }
+ unitRepository.saveAll(unitsWithBindings)
+ log.info("Successfully bind researches to units")
+ }
+
+ private fun bindResearchSergeants(sergeants: List, researches: List) {
+
+ val sergeantsWithBindings: List = researches.flatMap { research ->
+ research.researchModifiers.mapNotNull { modifier ->
+ sergeants.find { it.filename.replace(".rgd", "") == modifier.target }?.let {
+ it.affectedResearches.add(research)
+ it
+ }
+ }
+ }
+ sergeantRepository.saveAll(sergeantsWithBindings)
+ log.info("Successfully bind researches to sergeants")
+ }
+
+ private fun bindResearchBuildings(buildings: List, researches: List) {
+
+ val buildingsWithBindings: List = researches.flatMap { research ->
+ research.researchModifiers.mapNotNull { modifier ->
+ buildings.find { it.filename?.replace(".rgd", "") == modifier.target }?.let {
+ it.affectedResearches.add(research)
+ it
+ }
+ }
+ }
+ buildingRepository.saveAll(buildingsWithBindings)
+ log.info("Successfully bind researches to buildings")
+ }
+
+ private fun bindResearchWeapons(weapons: List, researches: List) {
+
+ val weaponsWithBindings: List = researches.flatMap { research ->
+ research.researchModifiers.mapNotNull { modifier ->
+ weapons.find { it.filename?.replace(".rgd", "") == modifier.target }?.let {
+ it.affectedResearches.add(research)
+ it
+ }
+ }
+ }
+ weaponRepository.saveAll(weaponsWithBindings)
+ log.info("Successfully bind researches to weapons")
+ }
+}
diff --git a/src/main/kotlin/com/dowstats/service/w40k/BuildingAddonRgdExtractService.kt b/src/main/kotlin/com/dowstats/service/w40k/BuildingAddonRgdExtractService.kt
index 8dad551..9443cff 100644
--- a/src/main/kotlin/com/dowstats/service/w40k/BuildingAddonRgdExtractService.kt
+++ b/src/main/kotlin/com/dowstats/service/w40k/BuildingAddonRgdExtractService.kt
@@ -1,7 +1,9 @@
package com.dowstats.service.w40k
-import com.dowstats.data.dto.BuildCost
import com.dowstats.data.entities.*
+import com.dowstats.data.entities.addon.AddonModifiers
+import com.dowstats.data.entities.addon.AddonRequirements
+import com.dowstats.data.entities.addon.BuildingAddon
import com.dowstats.data.rgd.RgdData
import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName
import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
@@ -10,23 +12,13 @@ import com.dowstats.data.rgd.RgdDataUtil.getStringByName
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
-import java.io.File
-import java.nio.file.Path
-import kotlin.io.path.exists
@Service
class BuildingAddonRgdExtractService @Autowired constructor(
- private val modAttribPathService: ModAttribPathService,
- private val iconsService: IconsService,
+ private val commonParseRgdService: CommonParseRgdService,
) {
-
val log = LoggerFactory.getLogger(BuildingAddonRgdExtractService::class.java)
- data class AddonTexts(
- val name: String?,
- val description: String?,
- )
-
fun extractToAddonEntity(
fileName: String,
modDictionary: Map,
@@ -37,14 +29,16 @@ class BuildingAddonRgdExtractService @Autowired constructor(
): BuildingAddon {
val addon = BuildingAddon()
-
- val nameAndDescription = getAddonNameAndDescription(addonRgdData, modDictionary)
- addon.name = nameAndDescription.name
- addon.description = nameAndDescription.description
addon.building = building
+
+ val uiInfoRgd = addonRgdData.getRgdTableByName("ui_info") ?: throw Exception("Could not find ui_info at $fileName")
+ val uiInfo = commonParseRgdService.getUiInfo(uiInfoRgd, modDictionary, modFolderData, mod, log)
+ addon.name = uiInfo.name
+ addon.description = uiInfo.description
+ addon.icon = uiInfo.iconPath
addon.filename = fileName
- val buildCost = getAddonCost(addonRgdData)
+ val buildCost = commonParseRgdService.getBuildCost(addonRgdData.getRgdTableByName("time_cost"))
addon.addonCostRequisition = buildCost.requisition
addon.addonCostPower = buildCost.power
addon.addonCostPopulation = buildCost.population
@@ -54,8 +48,6 @@ class BuildingAddonRgdExtractService @Autowired constructor(
addon.addonModifiers = getAddonModifiers(addon, addonRgdData).toMutableSet()
addon.addonRequirements = getAddonRequirements(addon, addonRgdData).toMutableSet()
- val addonIcon = convertIconAndReturnPath(addonRgdData, modFolderData, mod.name)
- addon.icon = addonIcon
addon.modId = mod.id
return addon
@@ -88,82 +80,11 @@ class BuildingAddonRgdExtractService @Autowired constructor(
it.addon = addon
it.reference = rTable.getStringByName("\$REF")
it.replaceWhenDone = rTable.getBooleanByName("replace_when_done") == true
- it.value = when(it.reference){
- AddonRequirements.REFERENCE_REQUIREMENT_POP -> rTable.getDoubleByName("population_required").toString()
- AddonRequirements.REFERENCE_REQUIREMENT_ADDON -> rTable.getStringByName("addon_name")
- AddonRequirements.REFERENCE_GLOBAL_REQUIREMENT_ADDON -> rTable.getStringByName("global_addon_name")
- AddonRequirements.REFERENCE_REQUIREMENT_STRUCTURE_EITHER -> rTable.getStringByName("structure_name_or") + ";" + rTable.getStringByName("structure_name_either")
- AddonRequirements.REFERENCE_REQUIREMENT_STRUCTURE -> rTable.getStringByName("structure_name")
- else -> null
- }
+ it.value = commonParseRgdService.getRequirementReference(it.reference, rTable, addon.filename!!, log)
}
}
} else null
} ?: emptyList()
}
-
- private fun getAddonCost(addonData: List): BuildCost {
-
- val cost = addonData.getRgdTableByName("time_cost")
-
- val costResources = cost?.getRgdTableByName("cost")
-
- return BuildCost(
- costResources?.getDoubleByName("requisition"),
- costResources?.getDoubleByName("power"),
- costResources?.getDoubleByName("population"),
- costResources?.getDoubleByName("faith"),
- costResources?.getDoubleByName("souls"),
- cost?.getDoubleByName("time_seconds")?.toInt()
- )
- }
-
- private fun getAddonNameAndDescription(addonData: List, modDictionary: Map): AddonTexts {
- val uiInfo = addonData.getRgdTableByName("ui_info")
-
- val nameRef = uiInfo?.getStringByName("screen_name_id")?.replace("$", "")
- val name = nameRef?.let {
- try {
- modDictionary[it.toInt()]
- } catch (e: Exception) {
- null
- }
- }
-
- val descriptionRefs = uiInfo?.getRgdTableByName("help_text_list")
- ?.map { (it.value as String).replace("$", "") }
- ?.filter { it != "0" && it != "tables\\text_table.lua" && it != "" }
- ?.sortedBy {
- try {
- it.toInt()
- } catch (e: Exception) {
- 0
- }
- }
-
- val description = try {
- descriptionRefs?.map { modDictionary[it.toInt()] }?.joinToString("\n")
- } catch (e: Exception) {
- log.warn("Error parsing ui description", e)
- null
- }
-
- return AddonTexts(name, description)
- }
-
-
- private fun convertIconAndReturnPath(
- buildingData: List,
- modFolderData: String,
- modName: String?
- ): String? {
- val iconPathInMod = buildingData
- .getRgdTableByName("ui_info")
- ?.getStringByName("icon_name")
-
- return iconPathInMod?.let { modAttribPathService.getIconPath(modFolderData, iconPathInMod) }
- ?.let { iconsService.convertTgaToJpegImage(iconPathInMod, it, modName) }
- }
-
}
diff --git a/src/main/kotlin/com/dowstats/service/w40k/BuildingRgdExtractService.kt b/src/main/kotlin/com/dowstats/service/w40k/BuildingRgdExtractService.kt
index 39b465d..a83ebd6 100644
--- a/src/main/kotlin/com/dowstats/service/w40k/BuildingRgdExtractService.kt
+++ b/src/main/kotlin/com/dowstats/service/w40k/BuildingRgdExtractService.kt
@@ -1,27 +1,21 @@
package com.dowstats.service.w40k
-import com.dowstats.data.dto.BuildCost
import com.dowstats.data.dto.BuildingDataToSave
import com.dowstats.data.entities.*
-import com.dowstats.data.repositories.UnitRepository
+import com.dowstats.data.entities.research.Research
import com.dowstats.data.rgd.RgdData
import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
import com.dowstats.data.rgd.RgdDataUtil.getIntByName
import com.dowstats.data.rgd.RgdDataUtil.getRgdTableByName
import com.dowstats.data.rgd.RgdDataUtil.getStringByName
-import com.dowstats.service.w40k.UnitRgdExtractService.ResourceIncome
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
-import java.io.File
-import java.nio.file.Path
-import kotlin.io.path.exists
@Service
class BuildingRgdExtractService @Autowired constructor(
- private val modAttribPathService: ModAttribPathService,
- private val iconsService: IconsService,
private val addonRgdExtractService: BuildingAddonRgdExtractService,
+ private val commonParseRgdService: CommonParseRgdService,
) {
val log = LoggerFactory.getLogger(BuildingRgdExtractService::class.java)
@@ -39,16 +33,12 @@ class BuildingRgdExtractService @Autowired constructor(
val weaponFilename: String,
)
- data class BuildingTexts(
- val name: String?,
- val description: String?,
- )
-
fun extractToBuildingEntity(
fileName: String,
modDictionary: Map,
buildingData: List,
weapons: Set,
+ researches: Set,
units: List,
race: Race,
modFolderData: String,
@@ -63,13 +53,16 @@ class BuildingRgdExtractService @Autowired constructor(
building.race = race
building.armorType = getBuildingArmourType(buildingData, armorTypes, "type_armour") ?: throw Exception("Cant get armor type")
building.armorType2 = getBuildingArmourType(buildingData, armorTypes, "type_armour_2")
-
- val nameAndDescription = getBuildingNameAndDescription(buildingData, modDictionary)
- building.name = nameAndDescription.name
- building.description = nameAndDescription.description
building.filename = fileName
- val buildCost = getBuildCost(buildingData)
+ val buildingUiInfo = buildingData.getRgdTableByName("ui_ext")
+ ?.getRgdTableByName("ui_info") ?: throw Exception("Could not find ui_info at $fileName")
+ val buildingUiData = commonParseRgdService.getUiInfo(buildingUiInfo, modDictionary, modFolderData, mod, log)
+ building.name = buildingUiData.name
+ building.description = buildingUiData.description
+ building.icon = buildingUiData.iconPath
+
+ val buildCost = commonParseRgdService.getBuildCost(buildingData.getRgdTableByName("cost_ext")?.getRgdTableByName("time_cost"))
building.buildCostRequisition = buildCost.requisition
building.buildCostPower = buildCost.power
building.buildCostPopulation = buildCost.population
@@ -77,7 +70,7 @@ class BuildingRgdExtractService @Autowired constructor(
building.buildCostSouls = buildCost.souls
building.buildCostTime = buildCost.time
- val incomeData = getResource(buildingData)
+ val incomeData = commonParseRgdService.getResourceIncome(buildingData.getRgdTableByName("resource_ext"))
building.faithIncome = incomeData.faith
building.powerIncome = incomeData.power
building.requisitionIncome = incomeData.requisition
@@ -94,6 +87,7 @@ class BuildingRgdExtractService @Autowired constructor(
building.repairMax = healthData.maxRepaires
building.units = getUnits(buildingData, units).toMutableSet()
+ building.researches = getResearches(buildingData, researches).toMutableSet()
val addons = getAddons(buildingData)
building.addons = addons?.mapNotNull {addonFileName ->
@@ -106,8 +100,6 @@ class BuildingRgdExtractService @Autowired constructor(
}
}?.toMutableSet()
- val buildingIcon = convertIconAndReturnPath(buildingData, modFolderData, mod.name)
- building.icon = buildingIcon
val buildingWeapons = getBuildingWeapon(buildingData)?.mapNotNull { weaponData ->
weapons.find {
@@ -135,54 +127,6 @@ class BuildingRgdExtractService @Autowired constructor(
return armorTypes.find { it.id == armorType?.replace("type_armour\\tp_", "")?.replace(".lua", "") }
}
- private fun getBuildCost(buildingData: List): BuildCost {
-
- val cost = buildingData.getRgdTableByName("cost_ext")
- ?.getRgdTableByName("time_cost")
-
- val costResources = cost?.getRgdTableByName("cost")
-
- return BuildCost(
- costResources?.getDoubleByName("requisition"),
- costResources?.getDoubleByName("power"),
- costResources?.getDoubleByName("population"),
- costResources?.getDoubleByName("faith"),
- costResources?.getDoubleByName("souls"),
- cost?.getDoubleByName("time_seconds")?.toInt()
- )
- }
-
- private fun getResource(buildingData: List): ResourceIncome {
- val resourceExt = buildingData.getRgdTableByName("resource_ext")
- return ResourceIncome(
- resourceExt?.getDoubleByName("faith_per_second")?.let { it * 10 },
- resourceExt?.getDoubleByName("power_per_second")?.let { it * 10 },
- resourceExt?.getDoubleByName("requisition_per_second")?.let { it * 10 },
- )
- }
-
- private fun getBuildingNameAndDescription(buildingData: List, modDictionary: Map): BuildingTexts {
- val uiInfo = buildingData.getRgdTableByName("ui_ext")
- ?.getRgdTableByName("ui_info")
-
- val nameRef = uiInfo?.getStringByName("screen_name_id")?.replace("$", "")
- val name = nameRef?.let { try{modDictionary[it.toInt()]} catch (e: Exception) { null } }
-
- val descriptionRefs = uiInfo?.getRgdTableByName("help_text_list")
- ?.map{(it.value as String).replace("$", "")}
- ?.filter{it != "0" && it != "tables\\text_table.lua" && it != ""}
- ?.sortedBy { try { it.toInt() } catch (e: Exception) { 0 } }
-
- val description = try {
- descriptionRefs?.map { modDictionary[it.toInt()] }?.joinToString ( "\n" )
- } catch(e:Exception) {
- log.warn("Error parsing ui description", e)
- null
- }
-
- return BuildingTexts(name, description)
- }
-
private fun getHealthData(buildingData: List): HealthData {
val healthExt = buildingData.getRgdTableByName("health_ext")
return HealthData(
@@ -225,17 +169,6 @@ class BuildingRgdExtractService @Autowired constructor(
}?.flatten()
- private fun convertIconAndReturnPath(buildingData: List, modFolderData: String, modName: String?): String? {
- val iconPathInMod = buildingData
- .getRgdTableByName("ui_ext")
- ?.getRgdTableByName("ui_info")
- ?.getStringByName("icon_name")
-
- return iconPathInMod?.let { modAttribPathService.getIconPath(modFolderData, iconPathInMod) }
- ?.let { iconsService.convertTgaToJpegImage(iconPathInMod, it, modName) }
- }
-
-
private fun getAddons(buildingData: List): List? = buildingData
.getRgdTableByName("addon_ext")
?.getRgdTableByName("addons")
@@ -254,10 +187,19 @@ class BuildingRgdExtractService @Autowired constructor(
?.mapNotNull { unit ->
if (unit.name.contains("squad_")) {
val fileName = unit.value.toString().split("\\").last().replace(".lua", ".rgd")
- units.find { it.filename == fileName }
+ units.find { it.filenameSquad == fileName }
} else null
} ?: emptyList()
}
+ private fun getResearches(buildingData: List, researches: Set): List {
+ return buildingData.getRgdTableByName("research_ext")
+ ?.getRgdTableByName("research_table")
+ ?.mapNotNull { research ->
+ if (research.name.contains("research_")) {
+ val fileName = research.value.toString().split("\\").last().replace(".lua", "")
+ researches.find { it.filename?.replace(".rgd", "") == fileName }
+ } else null
+ } ?: emptyList()
+ }
}
-
diff --git a/src/main/kotlin/com/dowstats/service/w40k/CommonParseRgdService.kt b/src/main/kotlin/com/dowstats/service/w40k/CommonParseRgdService.kt
new file mode 100644
index 0000000..e2ed2c4
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/service/w40k/CommonParseRgdService.kt
@@ -0,0 +1,137 @@
+package com.dowstats.service.w40k
+
+import com.dowstats.Metadata.Requirements
+import com.dowstats.data.dto.AreaEffect
+import com.dowstats.data.dto.BuildCost
+import com.dowstats.data.dto.ResourceIncome
+import com.dowstats.data.dto.UiInfo
+import com.dowstats.data.entities.Mod
+import com.dowstats.data.rgd.RgdData
+import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName
+import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
+import com.dowstats.data.rgd.RgdDataUtil.getRgdTableByName
+import com.dowstats.data.rgd.RgdDataUtil.getStringByName
+import org.slf4j.Logger
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.stereotype.Service
+
+@Service
+class CommonParseRgdService @Autowired constructor(
+ private val modAttribPathService: ModAttribPathService,
+ private val iconsService: IconsService,
+) {
+
+
+ fun getRequirementReference(ref: String?, rTable: List, fileName: String, log: Logger): String? = when (ref) {
+ Requirements.REFERENCE_REQUIREMENT_POP -> rTable.getDoubleByName("population_required").toString()
+ Requirements.REFERENCE_REQUIREMENT_ADDON -> rTable.getStringByName("addon_name")
+ Requirements.REFERENCE_GLOBAL_REQUIREMENT_ADDON -> rTable.getStringByName("global_addon_name")
+ Requirements.REFERENCE_REQUIREMENT_STRUCTURE_EITHER -> rTable.getStringByName("structure_name_or") + ";" + rTable.getStringByName(
+ "structure_name_either"
+ )
+ Requirements.REFERENCE_REQUIREMENT_STRUCTURE -> rTable.getStringByName("structure_name")
+ Requirements.REFERENCE_REQUIREMENT_RESEARCH -> rTable.getStringByName("research_name")+ ";" + rTable.getBooleanByName(
+ "research_must_not_be_complete"
+ )
+ else -> {
+ log.warn("Unknown requirement reference $ref at $fileName")
+ null
+ }
+ }
+
+ fun getBuildCost(cost: List?): BuildCost {
+
+ val costResources = cost?.getRgdTableByName("cost")
+
+ return BuildCost(
+ costResources?.getDoubleByName("requisition"),
+ costResources?.getDoubleByName("power"),
+ costResources?.getDoubleByName("population"),
+ costResources?.getDoubleByName("faith"),
+ costResources?.getDoubleByName("souls"),
+ cost?.getDoubleByName("time_seconds")?.toInt()
+ )
+ }
+
+ fun getResourceIncome(resourceExt: List?): ResourceIncome {
+ return ResourceIncome(
+ resourceExt?.getDoubleByName("faith_per_second")?.let { it * 10 },
+ resourceExt?.getDoubleByName("power_per_second")?.let { it * 10 },
+ resourceExt?.getDoubleByName("requisition_per_second")?.let { it * 10 },
+ )
+ }
+
+
+ fun getUiInfo(uiInfoRgdData: List, modDictionary: Map, modFolderData: String, mod: Mod, log: Logger): UiInfo {
+ val nameRef = uiInfoRgdData?.getStringByName("screen_name_id")?.replace("$", "")
+ val name = nameRef?.let { try { modDictionary[it.toInt()] } catch (e: Exception) { null } }
+
+ val descriptionRefs = uiInfoRgdData.getRgdTableByName("help_text_list")
+ ?.mapNotNull{try {
+ (it.value as String).replace("$", "")
+ } catch (e: Exception) {
+ log.error("Error parsing ui help_text weapon $name", e)
+ null
+ }}
+ ?.filter{it != "0" && it != "tables\\text_table.lua" && it != ""}
+ ?.sortedBy { try { it.toInt() } catch (e: Exception) { 0 } }
+
+ val description = try {
+ descriptionRefs?.map { try { modDictionary[it.toInt()] } catch (e: Exception) { "" } }?.joinToString ( "\n" )
+ } catch(e:Exception) {
+ log.warn("Error parsing ui description weapon $name", e)
+ null
+ }
+
+ val icon = try {
+ val iconPath = uiInfoRgdData.getStringByName("icon_name")
+
+ iconPath?.let { modAttribPathService.getIconPath(modFolderData, iconPath) }
+ ?.let { iconsService.convertTgaToJpegImage(iconPath, it, mod.name) }
+ } catch (e: Exception) {
+ log.error("Error parsing ui icon path for weapon $name", e)
+ null
+ }
+
+ return UiInfo(name, description, icon)
+ }
+
+ fun getAreaEffectData(weaponData: List): AreaEffect {
+ val areaEffect = weaponData.getRgdTableByName("area_effect")
+
+ val areaEffectInformation = areaEffect?.getRgdTableByName("area_effect_information")
+ val cantHaveRadius = areaEffectInformation?.getRgdTableByName("area_type")?.getStringByName("\$REF")?.contains("tp_area_effect_point") == true
+ val damageRadius = if(cantHaveRadius) 0.0 else areaEffectInformation?.getDoubleByName("radius") ?: 0.0
+
+ val throwData = areaEffect?.getRgdTableByName("throw_data")
+ val forceMin = throwData?.getDoubleByName("force_min") ?: 0.0
+ val forceMax = throwData?.getDoubleByName("force_max") ?: 0.0
+
+ val armourDamage = areaEffect
+ ?.getRgdTableByName("weapon_damage")
+ ?.getRgdTableByName("armour_damage")
+ val minDamage = armourDamage?.getDoubleByName("min_damage") ?: 0.0
+ val maxDamage = armourDamage?.getDoubleByName("max_damage") ?: 0.0
+ val minDamageValue = armourDamage?.getDoubleByName("min_damage_value") ?: 0.0
+ val moraleDamage = armourDamage?.getDoubleByName("morale_damage") ?: 0.0
+
+
+ val defaultArmourPiercing = armourDamage?.getDoubleByName("armour_piercing") ?: 0.0
+ val weaponDmgMap: Map =
+ armourDamage?.getRgdTableByName("armour_piercing_types")?.mapNotNull { armour_piercing ->
+ if (armour_piercing.name.contains("entry")) {
+ val entry = armour_piercing.value as List
+ val dmgType = entry.getRgdTableByName("armour_type")?.getStringByName("\$REF")?.replace("type_armour\\tp_","")?.replace(".lua","")
+ val dmgValue = entry.getDoubleByName("armour_piercing_value")
+ dmgType!! to dmgValue!!
+ } else null
+ }?.toMap() ?: emptyMap()
+
+
+
+ return AreaEffect(minDamage, maxDamage, damageRadius, forceMin, forceMax, minDamageValue, moraleDamage, weaponDmgMap, defaultArmourPiercing)
+ }
+
+
+}
+
diff --git a/src/main/kotlin/com/dowstats/service/w40k/IconsService.kt b/src/main/kotlin/com/dowstats/service/w40k/IconsService.kt
index 5afc3d4..bf03ccf 100644
--- a/src/main/kotlin/com/dowstats/service/w40k/IconsService.kt
+++ b/src/main/kotlin/com/dowstats/service/w40k/IconsService.kt
@@ -43,6 +43,7 @@ class IconsService @Autowired constructor(
null
} else {
pathToSave.replace("${storageConfig.iconsStorage.replace("/", File.separator)}${File.separator}", "")
+ .replace("${File.separator}${File.separator}","${File.separator}")
}
} catch (e: Exception) {
log.warn("Can't convert icon $iconPathInMod", e)
diff --git a/src/main/kotlin/com/dowstats/service/w40k/ModAttribPathService.kt b/src/main/kotlin/com/dowstats/service/w40k/ModAttribPathService.kt
index 0cc5390..6510ffb 100644
--- a/src/main/kotlin/com/dowstats/service/w40k/ModAttribPathService.kt
+++ b/src/main/kotlin/com/dowstats/service/w40k/ModAttribPathService.kt
@@ -26,6 +26,9 @@ class ModAttribPathService @Autowired constructor(
fun getWeaponAttribsPath(modFolderData: String): String =
"$modFolderData${File.separator}attrib${File.separator}weapon"
+ fun getResearchAttribsPath(modFolderData: String): String =
+ "$modFolderData${File.separator}attrib${File.separator}research"
+
fun getAddonAttribsPath(modFolderData: String): String =
"$modFolderData${File.separator}attrib${File.separator}addons"
diff --git a/src/main/kotlin/com/dowstats/service/w40k/ModParserService.kt b/src/main/kotlin/com/dowstats/service/w40k/ModParserService.kt
index 5ea18fc..90403bb 100644
--- a/src/main/kotlin/com/dowstats/service/w40k/ModParserService.kt
+++ b/src/main/kotlin/com/dowstats/service/w40k/ModParserService.kt
@@ -1,8 +1,10 @@
package com.dowstats.service.w40k
import com.dowstats.data.entities.*
+import com.dowstats.data.entities.research.Research
import com.dowstats.data.repositories.*
import com.dowstats.data.rgd.RgdData
+import com.dowstats.service.postparsing.PostParsingService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.lang.Exception
@@ -17,6 +19,7 @@ import kotlin.io.path.name
class ModParserService @Autowired constructor(
val rgdParserService: RgdParserService,
val unitRgdExtractService: UnitRgdExtractService,
+ val researchRgdExtractService: ResearchRgdExtractService,
val raceRepository: RaceRepository,
val armorTypeRepository: ArmorTypeRepository,
val unitRepository: UnitRepository,
@@ -26,6 +29,9 @@ class ModParserService @Autowired constructor(
val modAttribPathService: ModAttribPathService,
val buildingRepository: BuildingRepository,
val buildingExtractService: BuildingRgdExtractService,
+ val postParsingService: PostParsingService,
+ private val researchRepository: ResearchRepository,
+ private val modRepository: ModRepository,
) {
val defaultDictionary: MutableMap = mutableMapOf()
@@ -56,6 +62,7 @@ class ModParserService @Autowired constructor(
fun parseModFilesAndSaveToDb(mod: Mod) {
log.info("Start parse mod files ${mod.technicalName}:${mod.version}")
+ modRepository.clearModData(mod.id!!)
val modFolderData = modAttribPathService.getModFolderData(mod.technicalName!!, mod.version!!)
val racesList = Files.walk(Path(modAttribPathService.getSbpsAttribsFolderPath(modFolderData)), 1)
@@ -78,9 +85,14 @@ class ModParserService @Autowired constructor(
val enrichedModDictionary = defaultDictionary + modDictionary
val weapons = saveWeapons(modFolderData, mod, armorTypes, enrichedModDictionary)
+ val researches = saveResearches(modFolderData, mod, enrichedModDictionary)
saveUnits(modFolderData, weapons, racesList, armorTypes, mod, enrichedModDictionary)
+ saveBuildings(modFolderData, weapons, researches, racesList, armorTypes, mod, enrichedModDictionary)
+
+ modRepository.removeCampaignEntities(mod.id!!)
+ postParsingService.bindResearch(mod)
+ log.info("Complete parse mod ${mod.technicalName}:${mod.version}")
- saveBuildings(modFolderData, weapons, racesList, armorTypes, mod, enrichedModDictionary)
}
@@ -110,6 +122,49 @@ class ModParserService @Autowired constructor(
return modDictionary
}
+
+ private fun saveResearches(
+ modFolderData: String,
+ mod: Mod,
+ modDictionary: Map
+ ): Set {
+
+ val classicRgdDataResearches =
+ rgdParserService.parseFolderToRgdFiles(
+ modAttribPathService.getResearchAttribsPath(
+ modAttribPathService.pathToWanilaData,
+ )
+ )
+ val modRgdDataResearches =
+ rgdParserService.parseFolderToRgdFiles(
+ modAttribPathService.getResearchAttribsPath(
+ modFolderData,
+ )
+ )
+
+ val researchesFull = classicRgdDataResearches + modRgdDataResearches
+
+ val researches = researchesFull.mapNotNull { researchData ->
+ try {
+ researchRgdExtractService.extractToResearchEntity(
+ researchData.key,
+ modDictionary,
+ researchData.value,
+ modFolderData,
+ mod,
+ )
+ } catch (e: Exception) {
+ log.error("Can't extract ${researchData.key}", e)
+ null
+ }
+ }
+ return try {
+ researchRepository.saveAll(researches).toSet()
+ } catch (e: Exception) {
+ throw e
+ }
+ }
+
private fun saveUnits(
modFolderData: String,
weapons: Set,
@@ -173,6 +228,7 @@ class ModParserService @Autowired constructor(
try {
unitRgdExtractService.extractToUnitEntity(
squadRgdData.key,
+ baseUnitName,
modDictionary,
squadRgdData.value,
unitRgdData,
@@ -230,6 +286,7 @@ class ModParserService @Autowired constructor(
sergeantRepository.save(sergeant)
}
} catch (e: Exception) {
+ log.error("Cant save unit ${unitDataToSave.unit.name}", e)
throw e
}
}
@@ -239,6 +296,7 @@ class ModParserService @Autowired constructor(
private fun saveBuildings(
modFolderData: String,
weapons: Set,
+ researches: Set,
racesList: List,
armorTypes: Set,
mod: Mod, modDictionary: Map
@@ -282,6 +340,7 @@ class ModParserService @Autowired constructor(
modDictionary,
structure.value,
weapons,
+ researches,
raceUnits,
race,
modFolderData,
@@ -356,4 +415,6 @@ class ModParserService @Autowired constructor(
}
}
+
+
}
diff --git a/src/main/kotlin/com/dowstats/service/w40k/ResearchRgdExtractService.kt b/src/main/kotlin/com/dowstats/service/w40k/ResearchRgdExtractService.kt
new file mode 100644
index 0000000..a871ede
--- /dev/null
+++ b/src/main/kotlin/com/dowstats/service/w40k/ResearchRgdExtractService.kt
@@ -0,0 +1,88 @@
+package com.dowstats.service.w40k
+
+import com.dowstats.data.entities.*
+import com.dowstats.data.entities.research.Research
+import com.dowstats.data.entities.research.ResearchModifiers
+import com.dowstats.data.entities.research.ResearchRequirements
+import com.dowstats.data.rgd.RgdData
+import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
+import com.dowstats.data.rgd.RgdDataUtil.getRgdTableByName
+import com.dowstats.data.rgd.RgdDataUtil.getStringByName
+import org.slf4j.LoggerFactory
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.stereotype.Service
+
+@Service
+class ResearchRgdExtractService @Autowired constructor(
+ private val commonParseRgdService: CommonParseRgdService,
+) {
+
+ val log = LoggerFactory.getLogger(ResearchRgdExtractService::class.java)
+
+ fun extractToResearchEntity(
+ fileName: String,
+ modDictionary: Map,
+ researchData: List,
+ modFolderData: String,
+ mod: Mod,
+ ): Research {
+
+ val research = Research()
+ research.filename = fileName
+
+ val uiInfo = researchData.getRgdTableByName("ui_info") ?: throw Exception("Could not find ui_info at $fileName")
+ val researchUiInfo = commonParseRgdService.getUiInfo(uiInfo, modDictionary, modFolderData, mod, log)
+ research.name = researchUiInfo.name
+ research.description = researchUiInfo.description
+ research.icon = researchUiInfo.iconPath
+
+ val cost = commonParseRgdService.getBuildCost(researchData.getRgdTableByName("time_cost"))
+
+ research.costRequisition = cost.requisition
+ research.costPower = cost.power
+ research.costFaith = cost.faith
+ research.costSouls = cost.souls
+ research.costTime = cost.time
+ research.researchModifiers = getResearchModifiers(research, researchData).toMutableSet()
+ research.addonRequirements = getResearchRequirements(research, researchData).toMutableSet()
+
+ research.modId = mod.id
+
+ return research
+ }
+
+ private fun getResearchModifiers(research: Research, researchData: List): List {
+ val modifiers = researchData.getRgdTableByName("modifiers")
+ return modifiers?.mapNotNull { m ->
+ if (m.name.contains("modifier_")) {
+ val mTable = m.value as List
+ if (mTable.getStringByName("\$REF") == "modifiers\\no_modifier.lua") null else {
+ ResearchModifiers().also {
+ it.research = research
+ it.reference = mTable.getStringByName("\$REF")
+ it.usageType = mTable.getRgdTableByName("usage_type")?.getStringByName("\$REF")
+ it.target = mTable.getStringByName("target_type_name")
+ it.value = mTable.getDoubleByName("value")
+ }
+ }
+ } else null
+ } ?: emptyList()
+ }
+
+ private fun getResearchRequirements(research: Research, researchData: List): List {
+ val requirements = researchData.getRgdTableByName("requirements")
+ return requirements?.mapNotNull { r ->
+ if (r.name.contains("required_")) {
+ val rTable = r.value as List
+ if (rTable.getStringByName("\$REF") == "requirements\\required_none.lua") null else {
+ ResearchRequirements().also {
+ it.research = research
+ it.reference = rTable.getStringByName("\$REF")
+ it.value = commonParseRgdService.getRequirementReference(it.reference, rTable, research.filename!!, log)
+ }
+ }
+ } else null
+ } ?: emptyList()
+ }
+
+}
diff --git a/src/main/kotlin/com/dowstats/service/w40k/RgdParserService.kt b/src/main/kotlin/com/dowstats/service/w40k/RgdParserService.kt
index bd10861..7ac0a6a 100644
--- a/src/main/kotlin/com/dowstats/service/w40k/RgdParserService.kt
+++ b/src/main/kotlin/com/dowstats/service/w40k/RgdParserService.kt
@@ -13,7 +13,7 @@ import java.nio.ByteBuffer
class RgdParserService @Autowired constructor(
) {
- val log = LoggerFactory.getLogger(WeaponRgdExtractService::class.java)
+ val log = LoggerFactory.getLogger(RgdParserService::class.java)
val zeroByte: Byte = 0
diff --git a/src/main/kotlin/com/dowstats/service/w40k/SergantRgdExtractService.kt b/src/main/kotlin/com/dowstats/service/w40k/SergantRgdExtractService.kt
index 4f9b38a..9d5fb0e 100644
--- a/src/main/kotlin/com/dowstats/service/w40k/SergantRgdExtractService.kt
+++ b/src/main/kotlin/com/dowstats/service/w40k/SergantRgdExtractService.kt
@@ -7,18 +7,13 @@ import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
import com.dowstats.data.rgd.RgdDataUtil.getIntByName
import com.dowstats.data.rgd.RgdDataUtil.getRgdTableByName
import com.dowstats.data.rgd.RgdDataUtil.getStringByName
-import com.dowstats.service.w40k.UnitRgdExtractService.ResourceIncome
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
-import java.io.File
-import java.nio.file.Path
-import kotlin.io.path.exists
@Service
class SergeantRgdExtractService @Autowired constructor(
- private val modAttribPathService: ModAttribPathService,
- private val iconsService: IconsService,
+ private val commonParseRgdService: CommonParseRgdService,
) {
val log = LoggerFactory.getLogger(SergeantRgdExtractService::class.java)
@@ -42,11 +37,6 @@ class SergeantRgdExtractService @Autowired constructor(
val upTime: Double?,
)
- data class SquadTexts(
- val name: String?,
- val description: String?,
- )
-
fun extractToSergeantEntity(
fileName: String,
modDictionary: Map,
@@ -69,19 +59,23 @@ class SergeantRgdExtractService @Autowired constructor(
sergeant.armorType = getUnitArmorType(sergeantData, armorTypes, "type_armour") ?: throw Exception("Cant get armor type")
sergeant.armorType2 = getUnitArmorType(sergeantData, armorTypes, "type_armour_2")
-
- val nameAndDescription = getSergeantNameAndDescription(sergeantData, modDictionary)
- sergeant.name = nameAndDescription.name
- sergeant.description = nameAndDescription.description
sergeant.filename = fileName
+ val sergeantUiRgd = sergeantData.getRgdTableByName("ui_ext")
+ ?.getRgdTableByName("ui_info") ?: throw Exception("Could not find ui_info at $fileName")
+ val sergeantUiInfo = commonParseRgdService.getUiInfo(sergeantUiRgd, modDictionary, modFolderData, mod, log)
+ sergeant.name = sergeantUiInfo.name
+ sergeant.description = sergeantUiInfo.description
+ sergeant.icon = sergeantUiInfo.iconPath
+
+
val healthData = getHealthAndMoraleDeathPenaltyData(sergeantData)
sergeant.health = healthData.hitpoints?.toInt()
sergeant.armour = healthData.armour
sergeant.healthRegeneration = healthData.regeneration
sergeant.moraleDeathPenalty = healthData.moraleDeathPenalty?.toInt()
- val incomeData = getResource(sergeantData)
+ val incomeData = commonParseRgdService.getResourceIncome(sergeantData.getRgdTableByName("resource_ext"))
sergeant.faithIncome = incomeData.faith
sergeant.powerIncome = incomeData.power
sergeant.requisitionIncome = incomeData.requisition
@@ -93,8 +87,7 @@ class SergeantRgdExtractService @Autowired constructor(
sergeant.mass = massData.mass
sergeant.upTime = massData.upTime
- val unitIcon = convertSergeantIconAndReturnPath(sergeantData, modFolderData, mod.name)
- sergeant.icon = unitIcon
+ sergeant.modId = mod.id!!
val sergeantWeapons = getSergeantWeapons(sergeantData)?.mapNotNull { weaponData ->
weapons.find {
@@ -119,29 +112,6 @@ class SergeantRgdExtractService @Autowired constructor(
return armorTypes.find { it.id == armorType?.replace("type_armour\\tp_", "")?.replace(".lua", "") }
}
- private fun getSergeantNameAndDescription(sergeantData: List, modDictionary: Map): SquadTexts {
- val uiInfo = sergeantData.getRgdTableByName("ui_ext")
- ?.getRgdTableByName("ui_info")
-
-
- val nameRef = uiInfo?.getStringByName("screen_name_id")?.replace("$", "")
- val name = nameRef?.let { try{modDictionary[it.toInt()]} catch (e: Exception) { null } }
-
- val descriptionRefs = uiInfo?.getRgdTableByName("help_text_list")
- ?.map{(it.value as String).replace("$", "")}
- ?.filter{it != "0" && it != "tables\\text_table.lua" && it != ""}
- ?.sortedBy { try { it.toInt() } catch (e: Exception) { 0 } }
-
- val description = try {
- descriptionRefs?.map { modDictionary[it.toInt()] }?.joinToString ( "\n" )
- } catch(e:Exception) {
- log.warn("Error parsing ui description", e)
- null
- }
-
- return SquadTexts(name, description)
- }
-
private fun getHealthAndMoraleDeathPenaltyData(unitData: List): HealthAndMoraleDeathData {
val healthExt = unitData.getRgdTableByName("health_ext")
@@ -153,14 +123,6 @@ class SergeantRgdExtractService @Autowired constructor(
)
}
- private fun getResource(sergeantData: List): ResourceIncome {
- val resourceExt = sergeantData.getRgdTableByName("resource_ext")
- return ResourceIncome(
- resourceExt?.getDoubleByName("faith_per_second")?.let { it * 10 },
- resourceExt?.getDoubleByName("power_per_second")?.let { it * 10 },
- resourceExt?.getDoubleByName("requisition_per_second")?.let { it * 10 },
- )
- }
private fun getMassData(unitData: List): MassData {
val massDataRgd = unitData
@@ -201,14 +163,4 @@ class SergeantRgdExtractService @Autowired constructor(
} else null
}?.flatten()
- private fun convertSergeantIconAndReturnPath(sergeantData: List, modFolderData: String, modName: String?): String? {
- val iconPathInMod = sergeantData
- .getRgdTableByName("ui_ext")
- ?.getRgdTableByName("ui_info")
- ?.getStringByName("icon_name")
-
- return iconPathInMod?.let { modAttribPathService.getIconPath(modFolderData, iconPathInMod) }
- ?.let { iconsService.convertTgaToJpegImage(iconPathInMod, it, modName) }
- }
-
}
diff --git a/src/main/kotlin/com/dowstats/service/w40k/UnitRgdExtractService.kt b/src/main/kotlin/com/dowstats/service/w40k/UnitRgdExtractService.kt
index 598ac8b..805d762 100644
--- a/src/main/kotlin/com/dowstats/service/w40k/UnitRgdExtractService.kt
+++ b/src/main/kotlin/com/dowstats/service/w40k/UnitRgdExtractService.kt
@@ -16,8 +16,7 @@ import org.springframework.stereotype.Service
@Service
class UnitRgdExtractService @Autowired constructor(
- private val modAttribPathService: ModAttribPathService,
- private val iconsService: IconsService,
+ private val commonParseRgdService: CommonParseRgdService,
private val sergeantRgdExtractService: SergeantRgdExtractService,
) {
@@ -36,12 +35,6 @@ class UnitRgdExtractService @Autowired constructor(
val percentCost: Int?,
)
- data class ResourceIncome(
- val faith: Double?,
- val power: Double?,
- val requisition: Double?,
- )
-
data class MoraleData(
val max: Double?,
val broken: Double?,
@@ -58,13 +51,10 @@ class UnitRgdExtractService @Autowired constructor(
val upTime: Double?,
)
- data class UnitTexts(
- val name: String?,
- val description: String?,
- )
fun extractToUnitEntity(
- fileName: String,
+ fileNameSquad: String,
+ fileNameUnit: String,
modDictionary: Map,
squadData: List,
unitData: List,
@@ -84,10 +74,14 @@ class UnitRgdExtractService @Autowired constructor(
unit.armorType = getUnitArmorType(unitData, armorTypes, "type_armour") ?: throw Exception("Cant get armor type")
unit.armorType2 = getUnitArmorType(unitData, armorTypes, "type_armour_2")
- val nameAndDescription = getUnitNameAndDescription(squadData, modDictionary)
- unit.name = nameAndDescription.name
- unit.description = nameAndDescription.description
- unit.filename = fileName
+ val squadUiInfo = squadData.getRgdTableByName("squad_ui_ext")
+ ?.getRgdTableByName("ui_info") ?: throw Exception("Could not find ui_info at $fileNameSquad")
+ val squadUiData = commonParseRgdService.getUiInfo(squadUiInfo, modDictionary, modFolderData, mod, log)
+ unit.name = squadUiData.name
+ unit.description = squadUiData.description
+ unit.icon = squadUiData.iconPath
+ unit.filenameSquad = fileNameSquad
+ unit.filenameUnit = fileNameUnit
val buildCost = getBuildCost(unitData, squadData)
unit.buildCostRequisition = buildCost.requisition
@@ -117,7 +111,7 @@ class UnitRgdExtractService @Autowired constructor(
unit.repairSpeed = repairData.healthPerSecond
unit.repairCostPercent = repairData.percentCost
- val incomeData = getResource(unitData)
+ val incomeData = commonParseRgdService.getResourceIncome(unitData.getRgdTableByName("resource_ext"))
unit.faithIncome = incomeData.faith
unit.powerIncome = incomeData.power
unit.requisitionIncome = incomeData.requisition
@@ -135,14 +129,14 @@ class UnitRgdExtractService @Autowired constructor(
unit.mass = massData.mass
unit.upTime = massData.upTime
- val reinforceData = getReinforceRgdData(squadData)
- val reinforceCostData = reinforceData?.getRgdTableByName("cost")
- unit.reinforceCostRequisition = getReinforceRequisition(reinforceCostData)
- unit.reinforceCostPower = getReinforcePower(reinforceCostData)
- unit.reinforceCostPopulation = getReinforcePopulation(reinforceCostData)
- unit.reinforceCostFaith = getReinforceFaith(reinforceCostData)
- unit.reinforceCostSouls = getReinforceSouls(reinforceCostData)
- unit.reinforceTime = getReinforceTime(reinforceData)
+ val reinforceCostRgdData = getReinforceCostRgdData(squadData)
+ val reinforceCostData = commonParseRgdService.getBuildCost(reinforceCostRgdData)
+ unit.reinforceCostRequisition = reinforceCostData.requisition
+ unit.reinforceCostPower = reinforceCostData.power
+ unit.reinforceCostPopulation = reinforceCostData.population
+ unit.reinforceCostFaith = reinforceCostData.faith
+ unit.reinforceCostSouls = reinforceCostData.souls
+ unit.reinforceTime = reinforceCostData.time
@@ -167,8 +161,6 @@ class UnitRgdExtractService @Autowired constructor(
unit.maxSergeants = sergeantsData.second
- val unitIcon = convertIconAndReturnPath(mod.name, squadData, modFolderData)
- unit.icon = unitIcon
val unitWeapons = getUnitWeapons(unitData, weapons)
@@ -201,11 +193,7 @@ class UnitRgdExtractService @Autowired constructor(
private fun getBuildCost(unitData: List, squadData: List): BuildCost {
- val cost = unitData.getRgdTableByName("cost_ext")
- ?.getRgdTableByName("time_cost")
-
- val costResources = cost
- ?.getRgdTableByName("cost")
+ val cost = commonParseRgdService.getBuildCost(unitData.getRgdTableByName("cost_ext")?.getRgdTableByName("time_cost"))
val minSquadSize = squadData.getRgdTableByName("squad_loadout_ext")
?.getDoubleByName("unit_min")?.toInt()
@@ -214,45 +202,15 @@ class UnitRgdExtractService @Autowired constructor(
cost?.let { it * (minSquadSize ?: 1) }
return BuildCost(
- getCost(costResources?.getDoubleByName("requisition")),
- getCost(costResources?.getDoubleByName("power")),
- getCost(costResources?.getDoubleByName("population")),
- getCost(costResources?.getDoubleByName("faith")),
- getCost(costResources?.getDoubleByName("souls")),
- getCost(cost?.getDoubleByName("time_seconds"))?.toInt()
+ getCost(cost.requisition),
+ getCost(cost.power),
+ getCost(cost.population),
+ getCost(cost.faith),
+ getCost(cost.souls),
+ getCost(cost.time?.toDouble())?.toInt()
)
}
- private fun getUnitNameAndDescription(squadData: List, modDictionary: Map): UnitTexts {
- val uiInfo = squadData.getRgdTableByName("squad_ui_ext")
- ?.getRgdTableByName("ui_info")
-
-
- val nameRef = uiInfo?.getStringByName("screen_name_id")?.replace("$", "")
- val name = nameRef?.let {
- try {
- modDictionary[it.toInt()]
- } catch (e: Exception) {
- null
- }
- }
-
- val descriptionRefs = uiInfo?.getRgdTableByName("help_text_list")
- ?.map { (it.value as String).replace("$", "") }
- ?.filter { it != "0" && it != "tables\\text_table.lua" && it != "" && it.toIntOrNull() != null }
- ?.sortedBy { it.toInt() }
-
- val description = try {
- descriptionRefs?.map {
- modDictionary[it.toInt()] }?.joinToString("\n")
- } catch (e: Exception) {
- log.warn("Error parsing ui description", e)
- null
- }
-
- return UnitTexts(name, description)
- }
-
private fun getSquadCap(squadData: List): Pair {
@@ -307,14 +265,6 @@ class UnitRgdExtractService @Autowired constructor(
)
}
- private fun getResource(unitData: List): ResourceIncome {
- val resourceExt = unitData.getRgdTableByName("resource_ext")
- return ResourceIncome(
- resourceExt?.getDoubleByName("faith_per_second")?.let { it * 10 },
- resourceExt?.getDoubleByName("power_per_second")?.let { it * 10 },
- resourceExt?.getDoubleByName("requisition_per_second")?.let { it * 10 },
- )
- }
private fun getMoraleData(squadData: List): MoraleData {
val moraleData = squadData.getRgdTableByName("squad_morale_ext")
@@ -346,28 +296,10 @@ class UnitRgdExtractService @Autowired constructor(
.getRgdTableByName("sight_ext")
?.getDoubleByName("keen_sight_radius")
- private fun getReinforceRgdData(squadData: List): List? = squadData
+ private fun getReinforceCostRgdData(squadData: List): List? = squadData
.getRgdTableByName("squad_reinforce_ext")
?.getRgdTableByName("cost")
- private fun getReinforceRequisition(reinforceData: List?): Int? = reinforceData
- ?.getIntByName("requisition")
-
- private fun getReinforcePower(reinforceData: List?): Int? = reinforceData
- ?.getIntByName("power")
-
- private fun getReinforcePopulation(reinforceData: List?): Int? = reinforceData
- ?.getIntByName("population")
-
- private fun getReinforceFaith(reinforceData: List?): Int? = reinforceData
- ?.getIntByName("faith")
-
- private fun getReinforceSouls(reinforceData: List?): Int? = reinforceData
- ?.getIntByName("souls")
-
- private fun getReinforceTime(reinforceData: List?): Int? = reinforceData
- ?.getIntByName("time_seconds")
-
private fun getUnitWeapons(reinforceData: List?, weapons: Set): List? = reinforceData
?.getRgdTableByName("combat_ext")
?.getRgdTableByName("hardpoints")
@@ -382,9 +314,9 @@ class UnitRgdExtractService @Autowired constructor(
it.mapNotNull { weapon ->
(weapon.value as? List)?.getStringByName("weapon")?.let {
if (it != "") {
- val weaponFileName = it.replace("weapon\\", "").replace(".lua", ".rgd")
+ val weaponFileName = it.replace("weapon\\", "").replace(".lua", "")
val weaponEntity = weapons.find {
- it.filename == weaponFileName
+ it.filename?.replace(".rgd", "") == weaponFileName
}
if(weaponEntity == null){
log.warn("Can't find weapon $weaponFileName")
@@ -418,19 +350,9 @@ class UnitRgdExtractService @Autowired constructor(
if (sergeantLeaderFilePath == null || sergeantLeaderFilePath == "") null else {
- val cost = sergeantRgdTable.getRgdTableByName("cost_time")
- val costResources = cost?.getRgdTableByName("cost")
-
SergeantData(
sergeantLeaderFilePath,
- BuildCost(
- costResources?.getDoubleByName("requisition"),
- costResources?.getDoubleByName("power"),
- costResources?.getDoubleByName("population"),
- costResources?.getDoubleByName("faith"),
- costResources?.getDoubleByName("souls"),
- cost?.getIntByName("time_seconds"),
- )
+ commonParseRgdService.getBuildCost(sergeantRgdTable.getRgdTableByName("cost_time"))
)
}
} else null
@@ -438,15 +360,4 @@ class UnitRgdExtractService @Autowired constructor(
return Pair(sergeantsData, maxSergeants)
}
-
- private fun convertIconAndReturnPath(modName: String?, squadData: List, modFolderData: String): String? {
- val iconPathInMod = squadData
- .getRgdTableByName("squad_ui_ext")
- ?.getRgdTableByName("ui_info")
- ?.getStringByName("icon_name")
-
- return iconPathInMod?.let { modAttribPathService.getIconPath(modFolderData, iconPathInMod) }
- ?.let { iconsService.convertTgaToJpegImage(iconPathInMod, it, modName) }
- }
-
}
diff --git a/src/main/kotlin/com/dowstats/service/w40k/WeaponRgdExtractService.kt b/src/main/kotlin/com/dowstats/service/w40k/WeaponRgdExtractService.kt
index cf98e3f..af21074 100644
--- a/src/main/kotlin/com/dowstats/service/w40k/WeaponRgdExtractService.kt
+++ b/src/main/kotlin/com/dowstats/service/w40k/WeaponRgdExtractService.kt
@@ -4,69 +4,40 @@ import com.dowstats.data.entities.ArmorType
import com.dowstats.data.entities.Mod
import com.dowstats.data.entities.Weapon
import com.dowstats.data.entities.WeaponArmorPiercing
-import com.dowstats.data.repositories.ArmorTypeRepository
import com.dowstats.data.rgd.RgdData
import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName
import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
-import com.dowstats.data.rgd.RgdDataUtil.getIntByName
import com.dowstats.data.rgd.RgdDataUtil.getRgdTableByName
-import com.dowstats.data.rgd.RgdDataUtil.getStringByName
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
-import java.io.File
import java.math.BigDecimal
-import java.nio.file.Path
-import kotlin.io.path.exists
@Service
class WeaponRgdExtractService @Autowired constructor(
- private val armorTypeRepository: ArmorTypeRepository,
- private val iconsService: IconsService,
- private val modAttribPathService: ModAttribPathService,
+ private val commonParseRgdService: CommonParseRgdService,
) {
val log = LoggerFactory.getLogger(WeaponRgdExtractService::class.java)
- data class BuildCost(
- val requisition: Int?,
- val power: Int?,
- val seconds: Int?
- )
-
- data class AreaEffectData(
- val minDamage: Double,
- val maxDamage: Double,
- val damageRadius: Double,
- val throwForceMin: Double,
- val throwForceMax: Double,
- val minDamageValue: Double,
- val moraleDamage: Double,
- val armourPiercing: List,
- )
-
- data class WeaponUiInfo(
- val name: String?,
- val description: String?,
- val iconPath: String?,
- val haveEquipButton: Boolean
- )
fun extractToWeaponEntity(weaponFileName: String, weaponData: List, mod: Mod, armorTypes: Set, modFolderData: String, modDictionary: Map): Weapon? {
val weapon = Weapon()
weapon.filename = weaponFileName
- val weaponUiData = getWeaponNameAndDescription(weaponData, modDictionary, modFolderData, mod)
+
+ val weaponUiInfo = weaponData.getRgdTableByName("ui_info") ?: throw Exception("Could not find ui_info at $weaponFileName")
+ val weaponUiData = commonParseRgdService.getUiInfo(weaponUiInfo, modDictionary, modFolderData, mod, log)
weapon.name = weaponUiData.name
weapon.icon = weaponUiData.iconPath
weapon.description = weaponUiData.description
- weapon.haveEquipButton = weaponUiData.haveEquipButton
+ weapon.haveEquipButton = weaponUiInfo.getBooleanByName("no_button")?.let { !it } ?: false
- val cost = getCost(weaponData)
- weapon.costRequisition = cost.requisition ?: 0
- weapon.costPower = cost.power ?: 0
- weapon.costTimeSeconds = cost.seconds ?: 0
+ val cost = commonParseRgdService.getBuildCost(weaponData.getRgdTableByName("cost"))
+ weapon.costRequisition = cost.requisition ?: 0.0
+ weapon.costPower = cost.power ?: 0.0
+ weapon.costTimeSeconds = cost.time ?: 0
weapon.accuracy = weaponData.getDoubleByName("accuracy") ?: 1.0
weapon.accuracyReductionMoving = weaponData.getDoubleByName("accuracy_reduction_when_moving")
weapon.minRange = weaponData.getDoubleByName("min_range")
@@ -79,14 +50,24 @@ class WeaponRgdExtractService @Autowired constructor(
weapon.canAttackGround = weaponData.getBooleanByName("can_attack_ground_units") ?: true
- val areaEffectData = getAreaEffectData(weaponData, armorTypes, weapon)
+ val areaEffectData = commonParseRgdService.getAreaEffectData(weaponData)
+
+ val armoursPiercing = armorTypes.map {
+ val weaponArmourPiercing = WeaponArmorPiercing()
+ weaponArmourPiercing.weapon = weapon
+ weaponArmourPiercing.armorType = it
+ val piercingValue = (areaEffectData.weaponDmgMap[it.id] ?: areaEffectData.defaultArmorPiercing).toBigDecimal()
+ weaponArmourPiercing.piercingValue = piercingValue.let {pv -> if(pv <= BigDecimal(100)) pv else BigDecimal(100) }
+ weaponArmourPiercing
+ }
+
weapon.minDamageValue = areaEffectData.minDamageValue
weapon.minDamage = areaEffectData.minDamage
weapon.maxDamage = areaEffectData.maxDamage
weapon.throwForceMin = areaEffectData.throwForceMin
weapon.throwForceMax = areaEffectData.throwForceMax
weapon.moraleDamage = areaEffectData.moraleDamage
- weapon.weaponPiercings = areaEffectData.armourPiercing
+ weapon.weaponPiercings = armoursPiercing
weapon.damageRadius = areaEffectData.damageRadius
weapon.modId = mod.id
@@ -95,94 +76,5 @@ class WeaponRgdExtractService @Autowired constructor(
} else weapon
}
- private fun getCost(weaponData: List): BuildCost {
- val costTable = weaponData.getRgdTableByName("cost")
- val costTime = costTable?.getIntByName("time_seconds")
- val costCost = costTable?.getRgdTableByName("cost")
- val power = costCost?.getIntByName("power")
- val requisition = costCost?.getIntByName("requisition")
- return BuildCost(requisition, power, costTime)
- }
- private fun getAreaEffectData(weaponData: List, armorTypes: Set, thisWeapon: Weapon): AreaEffectData {
- val areaEffect = weaponData.getRgdTableByName("area_effect")
-
- val areaEffectInformation = areaEffect?.getRgdTableByName("area_effect_information")
- val cantHaveRadius = areaEffectInformation?.getRgdTableByName("area_type")?.getStringByName("\$REF")?.contains("tp_area_effect_point") == true
- val damageRadius = if(cantHaveRadius) 0.0 else areaEffectInformation?.getDoubleByName("radius") ?: 0.0
-
- val throwData = areaEffect?.getRgdTableByName("throw_data")
- val forceMin = throwData?.getDoubleByName("force_min") ?: 0.0
- val forceMax = throwData?.getDoubleByName("force_max") ?: 0.0
-
- val armourDamage = areaEffect
- ?.getRgdTableByName("weapon_damage")
- ?.getRgdTableByName("armour_damage")
- val minDamage = armourDamage?.getDoubleByName("min_damage") ?: 0.0
- val maxDamage = armourDamage?.getDoubleByName("max_damage") ?: 0.0
- val minDamageValue = armourDamage?.getDoubleByName("min_damage_value") ?: 0.0
- val moraleDamage = armourDamage?.getDoubleByName("morale_damage") ?: 0.0
-
-
- val defaultArmourPiercing = armourDamage?.getDoubleByName("armour_piercing")
- val weaponDmgMap: Map =
- armourDamage?.getRgdTableByName("armour_piercing_types")?.mapNotNull { armour_piercing ->
- if (armour_piercing.name.contains("entry")) {
- val entry = armour_piercing.value as List
- val dmgType = entry.getRgdTableByName("armour_type")?.getStringByName("\$REF")?.replace("type_armour\\tp_","")?.replace(".lua","")
- val dmgValue = entry.getDoubleByName("armour_piercing_value")
- dmgType!! to dmgValue!!
- } else null
- }?.toMap() ?: emptyMap()
-
- val armoursPiercing = armorTypes.map {
- val weaponArmourPiercing = WeaponArmorPiercing()
- weaponArmourPiercing.weapon = thisWeapon
- weaponArmourPiercing.armorType = it
- val piercingValue = (weaponDmgMap[it.id] ?: defaultArmourPiercing)?.toBigDecimal()
- weaponArmourPiercing.piercingValue = piercingValue?.let {pv -> if(pv <= BigDecimal(100)) pv else BigDecimal(100) }
- weaponArmourPiercing
- }
-
- return AreaEffectData(minDamage, maxDamage, damageRadius, forceMin, forceMax, minDamageValue, moraleDamage, armoursPiercing)
- }
-
-
- private fun getWeaponNameAndDescription(weaponData: List, modDictionary: Map, modFolderData: String, mod: Mod): WeaponUiInfo {
- val weaponUiInfo = weaponData.getRgdTableByName("ui_info")
-
- val nameRef = weaponUiInfo?.getStringByName("screen_name_id")?.replace("$", "")
- val name = nameRef?.let { try { modDictionary[it.toInt()] } catch (e: Exception) { null } }
-
- val descriptionRefs = weaponUiInfo?.getRgdTableByName("help_text_list")
- ?.mapNotNull{try {
- (it.value as String).replace("$", "")
- } catch (e: Exception) {
- log.error("Error parsing ui help_text weapon $name", e)
- null
- }}
- ?.filter{it != "0" && it != "tables\\text_table.lua" && it != ""}
- ?.sortedBy { try { it.toInt() } catch (e: Exception) { 0 } }
-
- val description = try {
- descriptionRefs?.map { try { modDictionary[it.toInt()] } catch (e: Exception) { "" } }?.joinToString ( "\n" )
- } catch(e:Exception) {
- log.warn("Error parsing ui description weapon $name", e)
- null
- }
-
- val icon = try {
- val iconPath = weaponUiInfo?.getStringByName("icon_name")
-
- iconPath?.let { modAttribPathService.getIconPath(modFolderData, iconPath) }
- ?.let { iconsService.convertTgaToJpegImage(iconPath, it, mod.name) }
- } catch (e: Exception) {
- log.error("Error parsing ui icon path for weapon $name", e)
- null
- }
-
- val haveUpgradeButton = weaponUiInfo?.getBooleanByName("no_button")?.let { !it } ?: false
-
- return WeaponUiInfo(name, description, icon, haveUpgradeButton)
- }
}
diff --git a/src/main/resources/db/0.0.3/data/armor_types.json b/src/main/resources/db/0.0.3/data/armor_types.json
new file mode 100644
index 0000000..a4c0ea2
--- /dev/null
+++ b/src/main/resources/db/0.0.3/data/armor_types.json
@@ -0,0 +1,65 @@
+{
+ "databaseChangeLog": [
+ {
+ "changeSet": {
+ "id": "Update armor type names",
+ "author": "anibus",
+ "changes": [
+ {
+ "update": {
+ "columns": [
+ {
+ "column": {
+ "name": "name",
+ "value": "Infantry H.Med."
+ }
+ }
+ ],
+ "tableName": "armor_types",
+ "where": "name='Infantry Heavy Medium'"
+ }
+ },{
+ "update": {
+ "columns": [
+ {
+ "column": {
+ "name": "name",
+ "value": "Infantry H.High"
+ }
+ }
+ ],
+ "tableName": "armor_types",
+ "where": "name='Infantry Heavy High'"
+ }
+ },{
+ "update": {
+ "columns": [
+ {
+ "column": {
+ "name": "name",
+ "value": "Infantry Com."
+ }
+ }
+ ],
+ "tableName": "armor_types",
+ "where": "name='Commander'"
+ }
+ },{
+ "update": {
+ "columns": [
+ {
+ "column": {
+ "name": "name",
+ "value": "Vehicle Air"
+ }
+ }
+ ],
+ "tableName": "armor_types",
+ "where": "name='Air'"
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/db/0.0.3/procedures/delete_campaign_entities.sql b/src/main/resources/db/0.0.3/procedures/delete_campaign_entities.sql
new file mode 100644
index 0000000..2ce5684
--- /dev/null
+++ b/src/main/resources/db/0.0.3/procedures/delete_campaign_entities.sql
@@ -0,0 +1,11 @@
+CREATE OR REPLACE PROCEDURE delete_campaign_entities(mod_id_p bigint)
+ LANGUAGE SQL
+AS $$
+DELETE FROM units WHERE mod_id = mod_id_p AND (fileName_squad LIKE '%\_dxp3.%' OR fileName_squad LIKE '%\_dxp3.%' OR fileName_squad LIKE '%sp\_eldar\_%' OR fileName_squad LIKE '%\_sp\_%' OR fileName_squad LIKE '%\_sp.%' OR fileName_squad LIKE '%\_nis.%' OR fileName_squad LIKE '%\_interface\_relay.%' OR fileName_squad LIKE '%necron\_tunnel.rgd%' OR fileName_squad LIKE '%\_exarch\_council.%' OR fileName_squad LIKE '%\_dark\_reapers\_base.%' OR fileName_squad LIKE '%eldar\_deep\_strike\_building.rgd%' OR fileName_squad LIKE '%ork\_deep\_strike\_building.rgd%' OR fileName_squad LIKE '%\_caravel\_ai.rgd%' OR fileName_squad LIKE '%sisters\_tanktrap\_ai.rgd%' OR fileName_squad LIKE '%sisters\_hq\_ktgm.rgd%' OR fileName_squad LIKE '%tau\_squad\_slave\_murdered%' OR fileName_squad LIKE '%single\_player\_only%' OR fileName_squad LIKE '%space\_marine\_drop\_pod\_building.rgd%' OR fileName_squad LIKE '%advance\_sp%' OR fileName_squad LIKE '%\_no\_limit.rgd%');
+DELETE FROM buildings WHERE mod_id = mod_id_p AND (filename LIKE '%\_dxp3.%' OR filename LIKE '%\_dxp3.%' OR filename LIKE '%sp\_eldar\_%' OR filename LIKE '%\_sp\_%' OR filename LIKE '%\_sp.%' OR filename LIKE '%\_nis.%' OR filename LIKE '%\_interface\_relay.%' OR filename LIKE '%necron\_tunnel.rgd%' OR filename LIKE '%\_exarch\_council.%' OR filename LIKE '%\_dark\_reapers\_base.%' OR filename LIKE '%eldar\_deep\_strike\_building.rgd%' OR filename LIKE '%ork\_deep\_strike\_building.rgd%' OR filename LIKE '%\_caravel\_ai.rgd%' OR filename LIKE '%sisters\_tanktrap\_ai.rgd%' OR filename LIKE '%sisters\_hq\_ktgm.rgd%' OR filename LIKE '%tau\_squad\_slave\_murdered%' OR filename LIKE '%single\_player\_only%' OR filename LIKE '%space\_marine\_drop\_pod\_building.rgd%' OR filename LIKE '%advance\_sp%' OR filename LIKE '%night\_lords\_hq\_aep%' OR filename LIKE '%\_ktgm.rgd%' OR filename LIKE '%salamander\_hq\_aep.rgd%' OR filename LIKE '%\_no\_limit.rgd%');
+DELETE FROM weapons WHERE mod_id = mod_id_p AND (filename LIKE '%\_dxp3.%' OR filename LIKE '%\_dxp3.%' OR filename LIKE '%sp\_eldar\_%' OR filename LIKE '%\_sp\_%' OR filename LIKE '%\_sp.%' OR filename LIKE '%\_nis.%' OR filename LIKE '%\_interface\_relay.%' OR filename LIKE '%necron\_tunnel.rgd%' OR filename LIKE '%\_exarch\_council.%' OR filename LIKE '%\_dark\_reapers\_base.%' OR filename LIKE '%eldar\_deep\_strike\_building.rgd%' OR filename LIKE '%ork\_deep\_strike\_building.rgd%' OR filename LIKE '%\_caravel\_ai.rgd%' OR filename LIKE '%sisters\_tanktrap\_ai.rgd%' OR filename LIKE '%sisters\_hq\_ktgm.rgd%' OR filename LIKE '%tau\_squad\_slave\_murdered%' OR filename LIKE '%single\_player\_only%' OR filename LIKE '%space\_marine\_drop\_pod\_building.rgd%' OR filename LIKE '%advance\_sp%');
+DELETE FROM researches WHERE mod_id = mod_id_p AND (filename LIKE '%\_dxp3.%' OR filename LIKE '%\_dxp3.%' OR filename LIKE '%sp\_eldar\_%' OR filename LIKE '%\_sp\_%' OR filename LIKE '%\_sp.%' OR filename LIKE '%\_nis.%' OR filename LIKE '%\_interface\_relay.%' OR filename LIKE '%necron\_tunnel.rgd%' OR filename LIKE '%\_exarch\_council.%' OR filename LIKE '%\_dark\_reapers\_base.%' OR filename LIKE '%eldar\_deep\_strike\_building.rgd%' OR filename LIKE '%ork\_deep\_strike\_building.rgd%' OR filename LIKE '%\_caravel\_ai.rgd%' OR filename LIKE '%sisters\_tanktrap\_ai.rgd%' OR filename LIKE '%sisters\_hq\_ktgm.rgd%' OR filename LIKE '%tau\_squad\_slave\_murdered%' OR filename LIKE '%single\_player\_only%' OR filename LIKE '%space\_marine\_drop\_pod\_building.rgd%' OR filename LIKE '%advance\_sp%');
+DELETE FROM research_modifiers USING researches WHERE researches.mod_id = 3 AND researches.id = research_id AND (target LIKE '%\_dxp3%' OR target LIKE '%\_dxp3%' OR target LIKE '%sp\_eldar\_%' OR target LIKE '%\_sp\_%' OR target LIKE '%\_sp.%' OR target LIKE '%\_nis.%' OR target LIKE '%\_interface\_relay.%' OR target LIKE '%necron\_tunnel.rgd%' OR target LIKE '%\_exarch\_council.%' OR target LIKE '%\_dark\_reapers\_base.%' OR target LIKE '%eldar\_deep\_strike\_building.rgd%' OR target LIKE '%ork\_deep\_strike\_building.rgd%' OR target LIKE '%\_caravel\_ai.rgd%' OR target LIKE '%sisters\_tanktrap\_ai.rgd%' OR target LIKE '%sisters\_hq\_ktgm.rgd%' OR target LIKE '%tau\_squad\_slave\_murdered%' OR target LIKE '%single\_player\_only%' OR target LIKE '%space\_marine\_drop\_pod\_building.rgd%' OR target LIKE '%advance\_sp%');
+DELETE FROM building_addons USING buildings WHERE buildings.mod_id = 3 AND buildings.id = building_addons.building_id AND (building_addons.filename LIKE '%\_dxp3%' OR building_addons.filename LIKE '%\_dxp3%' OR building_addons.filename LIKE '%sp\_eldar\_%' OR building_addons.filename LIKE '%\_sp\_%' OR building_addons.filename LIKE '%\_sp.%' OR building_addons.filename LIKE '%\_nis.%' OR building_addons.filename LIKE '%\_interface\_relay.%' OR building_addons.filename LIKE '%necron\_tunnel.rgd%' OR building_addons.filename LIKE '%\_exarch\_council.%' OR building_addons.filename LIKE '%\_dark\_reapers\_base.%' OR building_addons.filename LIKE '%eldar\_deep\_strike\_building.rgd%' OR building_addons.filename LIKE '%ork\_deep\_strike\_building.rgd%' OR building_addons.filename LIKE '%\_caravel\_ai.rgd%' OR building_addons.filename LIKE '%sisters\_tanktrap\_ai.rgd%' OR building_addons.filename LIKE '%sisters\_hq\_ktgm.rgd%' OR building_addons.filename LIKE '%tau\_squad\_slave\_murdered%' OR building_addons.filename LIKE '%single\_player\_only%' OR building_addons.filename LIKE '%space\_marine\_drop\_pod\_building.rgd%' OR building_addons.filename LIKE '%advance\_sp%' OR building_addons.filename LIKE '%addon\_necron\_hq\_3%');
+DELETE FROM abilities WHERE mod_id = mod_id_p AND (filename LIKE '%\_dxp3.%' OR filename LIKE '%\_dxp3.%' OR filename LIKE '%sp\_eldar\_%' OR filename LIKE '%\_sp\_%' OR filename LIKE '%\_sp.%' OR filename LIKE '%\_nis.%' OR filename LIKE '%\_interface\_relay.%' OR filename LIKE '%necron\_tunnel.rgd%' OR filename LIKE '%\_exarch\_council.%' OR filename LIKE '%\_dark\_reapers\_base.%' OR filename LIKE '%eldar\_deep\_strike\_building.rgd%' OR filename LIKE '%ork\_deep\_strike\_building.rgd%' OR filename LIKE '%\_caravel\_ai.rgd%' OR filename LIKE '%sisters\_tanktrap\_ai.rgd%' OR filename LIKE '%sisters\_hq\_ktgm.rgd%' OR filename LIKE '%tau\_squad\_slave\_murdered%' OR filename LIKE '%single\_player\_only%' OR filename LIKE '%space\_marine\_drop\_pod\_building.rgd%' OR filename LIKE '%advance\_sp%');
+$$;
\ No newline at end of file
diff --git a/src/main/resources/db/0.0.3/procedures/delete_mod_data_procedure.sql b/src/main/resources/db/0.0.3/procedures/delete_mod_data_procedure.sql
new file mode 100644
index 0000000..3106e64
--- /dev/null
+++ b/src/main/resources/db/0.0.3/procedures/delete_mod_data_procedure.sql
@@ -0,0 +1,9 @@
+CREATE OR REPLACE PROCEDURE delete_mod_data(mod_id_p bigint)
+ LANGUAGE SQL
+AS $$
+DELETE FROM units WHERE mod_id = mod_id_p;
+DELETE FROM buildings WHERE mod_id = mod_id_p;
+DELETE FROM weapons WHERE mod_id = mod_id_p;
+DELETE FROM researches WHERE mod_id = mod_id_p;
+DELETE FROM abilities WHERE mod_id = mod_id_p;
+$$;
\ No newline at end of file
diff --git a/src/main/resources/db/0.0.3/schema/abilities.json b/src/main/resources/db/0.0.3/schema/abilities.json
new file mode 100644
index 0000000..ed8f627
--- /dev/null
+++ b/src/main/resources/db/0.0.3/schema/abilities.json
@@ -0,0 +1,94 @@
+{
+ "databaseChangeLog": [
+ {
+ "changeSet": {
+ "id": "Add abilities table",
+ "author": "anibus",
+ "changes": [
+ {
+ "createTable": {
+ "tableName": "abilities",
+ "columns": [
+ {
+ "column": {
+ "name": "id",
+ "type": "int",
+ "autoIncrement": true,
+ "constraints": {
+ "primaryKey": true,
+ "nullable": false
+ }
+ }
+ },
+ {
+ "column": {
+ "name": "filename",
+ "type": "varchar(255)",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ },{
+ "column": {
+ "name": "name",
+ "type": "varchar(255)"
+ }
+ },{
+ "column": {
+ "name": "description",
+ "type": "varchar(5000)"
+ }
+ },
+ {
+ "column": {
+ "name": "cost_requisition",
+ "type": "number"
+ }
+ },{
+ "column": {
+ "name": "cost_power",
+ "type": "number"
+ }
+ },{
+ "column": {
+ "name": "cost_faith",
+ "type": "number"
+ }
+ },
+ {
+ "column": {
+ "name": "cost_souls",
+ "type": "number"
+ }
+ },{
+ "column": {
+ "name": "icon",
+ "type": "varchar(128)"
+ }
+ },{
+ "column": {
+ "name": "mod_id",
+ "type": "int",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "addForeignKeyConstraint":
+ {
+ "baseColumnNames": "mod_id",
+ "baseTableName": "abilities",
+ "constraintName": "fk_abilities_mods",
+ "referencedColumnNames": "id",
+ "referencedTableName": "mods"
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/src/main/resources/db/0.0.3/schema/buildings_researches.json b/src/main/resources/db/0.0.3/schema/buildings_researches.json
new file mode 100644
index 0000000..950694d
--- /dev/null
+++ b/src/main/resources/db/0.0.3/schema/buildings_researches.json
@@ -0,0 +1,66 @@
+{
+ "databaseChangeLog": [
+ {
+ "changeSet": {
+ "id": "Add buildings_researches table",
+ "author": "anibus",
+ "changes": [
+ {
+ "createTable": {
+ "tableName": "buildings_researches",
+ "columns": [
+ {
+ "column": {
+ "name": "building_id",
+ "type": "int",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ },
+ {
+ "column": {
+ "name": "research_id",
+ "type": "int",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "addUniqueConstraint": {
+ "columnNames": "building_id, research_id",
+ "constraintName": "uc_buildings_researches_research_id_building_id",
+ "tableName": "buildings_researches"
+ }
+ },
+ {
+ "addForeignKeyConstraint":
+ {
+ "baseColumnNames": "building_id",
+ "baseTableName": "buildings_researches",
+ "constraintName": "fk_buildings_buildings_researches",
+ "referencedColumnNames": "id",
+ "referencedTableName": "buildings",
+ "onDelete": "CASCADE"
+ }
+ },
+ {
+ "addForeignKeyConstraint":
+ {
+ "baseColumnNames": "research_id",
+ "baseTableName": "buildings_researches",
+ "constraintName": "fk_researches_buildings_researches",
+ "referencedColumnNames": "id",
+ "referencedTableName": "researches",
+ "onDelete": "CASCADE"
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/src/main/resources/db/0.0.3/schema/research_modifiers.json b/src/main/resources/db/0.0.3/schema/research_modifiers.json
new file mode 100644
index 0000000..35b2b33
--- /dev/null
+++ b/src/main/resources/db/0.0.3/schema/research_modifiers.json
@@ -0,0 +1,69 @@
+{
+ "databaseChangeLog": [
+ {
+ "changeSet": {
+ "id": "Add research_modifiers table",
+ "author": "anibus",
+ "changes": [
+ {
+ "createTable": {
+ "tableName": "research_modifiers",
+ "columns": [
+ {
+ "column": {
+ "name": "id",
+ "type": "int",
+ "autoIncrement": true,
+ "constraints": {
+ "primaryKey": true,
+ "nullable": false
+ }
+ }
+ },{
+ "column": {
+ "name": "reference",
+ "type": "varchar(255)"
+ }
+ },{
+ "column": {
+ "name": "usage_type",
+ "type": "varchar(255)"
+ }
+ },{
+ "column": {
+ "name": "target",
+ "type": "varchar(255)"
+ }
+ },{
+ "column": {
+ "name": "value",
+ "type": "number"
+ }
+ },{
+ "column": {
+ "name": "research_id",
+ "type": "int",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "addForeignKeyConstraint":
+ {
+ "baseColumnNames": "research_id",
+ "baseTableName": "research_modifiers",
+ "constraintName": "fk_researches_research_modifiers",
+ "referencedColumnNames": "id",
+ "referencedTableName": "researches",
+ "onDelete": "CASCADE"
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/src/main/resources/db/0.0.3/schema/research_requirements.json b/src/main/resources/db/0.0.3/schema/research_requirements.json
new file mode 100644
index 0000000..825cb3e
--- /dev/null
+++ b/src/main/resources/db/0.0.3/schema/research_requirements.json
@@ -0,0 +1,59 @@
+{
+ "databaseChangeLog": [
+ {
+ "changeSet": {
+ "id": "Add research_requirements table",
+ "author": "anibus",
+ "changes": [
+ {
+ "createTable": {
+ "tableName": "research_requirements",
+ "columns": [
+ {
+ "column": {
+ "name": "id",
+ "type": "int",
+ "autoIncrement": true,
+ "constraints": {
+ "primaryKey": true,
+ "nullable": false
+ }
+ }
+ },{
+ "column": {
+ "name": "reference",
+ "type": "varchar(255)"
+ }
+ },{
+ "column": {
+ "name": "value",
+ "type": "varchar(255)"
+ }
+ },{
+ "column": {
+ "name": "research_id",
+ "type": "int",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "addForeignKeyConstraint":
+ {
+ "baseColumnNames": "research_id",
+ "baseTableName": "research_requirements",
+ "constraintName": "fk_research_requirements_researches",
+ "referencedColumnNames": "id",
+ "referencedTableName": "researches",
+ "onDelete": "CASCADE"
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/src/main/resources/db/0.0.3/schema/researches.json b/src/main/resources/db/0.0.3/schema/researches.json
new file mode 100644
index 0000000..a105dde
--- /dev/null
+++ b/src/main/resources/db/0.0.3/schema/researches.json
@@ -0,0 +1,99 @@
+{
+ "databaseChangeLog": [
+ {
+ "changeSet": {
+ "id": "Add researches table",
+ "author": "anibus",
+ "changes": [
+ {
+ "createTable": {
+ "tableName": "researches",
+ "columns": [
+ {
+ "column": {
+ "name": "id",
+ "type": "int",
+ "autoIncrement": true,
+ "constraints": {
+ "primaryKey": true,
+ "nullable": false
+ }
+ }
+ },
+ {
+ "column": {
+ "name": "filename",
+ "type": "varchar(255)",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ },{
+ "column": {
+ "name": "name",
+ "type": "varchar(4096)"
+ }
+ },{
+ "column": {
+ "name": "description",
+ "type": "varchar(5000)"
+ }
+ },
+ {
+ "column": {
+ "name": "cost_requisition",
+ "type": "number"
+ }
+ },{
+ "column": {
+ "name": "cost_power",
+ "type": "number"
+ }
+ },{
+ "column": {
+ "name": "cost_faith",
+ "type": "number"
+ }
+ },{
+ "column": {
+ "name": "cost_souls",
+ "type": "number"
+ }
+ },{
+ "column": {
+ "name": "cost_time",
+ "type": "int"
+ }
+ },{
+ "column": {
+ "name": "mod_id",
+ "type": "int",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ },
+ {
+ "column": {
+ "name": "icon",
+ "type": "varchar(128)"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "addForeignKeyConstraint":
+ {
+ "baseColumnNames": "mod_id",
+ "baseTableName": "researches",
+ "constraintName": "fk_researches_mods",
+ "referencedColumnNames": "id",
+ "referencedTableName": "mods"
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/src/main/resources/db/0.0.3/schema/researches_affected_buildings.json b/src/main/resources/db/0.0.3/schema/researches_affected_buildings.json
new file mode 100644
index 0000000..b2dba3e
--- /dev/null
+++ b/src/main/resources/db/0.0.3/schema/researches_affected_buildings.json
@@ -0,0 +1,66 @@
+{
+ "databaseChangeLog": [
+ {
+ "changeSet": {
+ "id": "Add researches_affected_buildings table",
+ "author": "anibus",
+ "changes": [
+ {
+ "createTable": {
+ "tableName": "researches_affected_buildings",
+ "columns": [
+ {
+ "column": {
+ "name": "research_id",
+ "type": "int",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ },
+ {
+ "column": {
+ "name": "building_id",
+ "type": "int",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "addUniqueConstraint": {
+ "columnNames": "research_id, building_id",
+ "constraintName": "uc_researches_affected_buildings_research_id_building_id",
+ "tableName": "researches_affected_buildings"
+ }
+ },
+ {
+ "addForeignKeyConstraint":
+ {
+ "baseColumnNames": "research_id",
+ "baseTableName": "researches_affected_buildings",
+ "constraintName": "fk_researches_researches_affected_buildings",
+ "referencedColumnNames": "id",
+ "referencedTableName": "researches",
+ "onDelete": "CASCADE"
+ }
+ },
+ {
+ "addForeignKeyConstraint":
+ {
+ "baseColumnNames": "building_id",
+ "baseTableName": "researches_affected_buildings",
+ "constraintName": "fk_buildings_researches_affected_buildings",
+ "referencedColumnNames": "id",
+ "referencedTableName": "buildings",
+ "onDelete": "CASCADE"
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/src/main/resources/db/0.0.3/schema/researches_affected_sergeants.json b/src/main/resources/db/0.0.3/schema/researches_affected_sergeants.json
new file mode 100644
index 0000000..51c7f86
--- /dev/null
+++ b/src/main/resources/db/0.0.3/schema/researches_affected_sergeants.json
@@ -0,0 +1,66 @@
+{
+ "databaseChangeLog": [
+ {
+ "changeSet": {
+ "id": "Add researches_affected_sergeants table",
+ "author": "anibus",
+ "changes": [
+ {
+ "createTable": {
+ "tableName": "researches_affected_sergeants",
+ "columns": [
+ {
+ "column": {
+ "name": "research_id",
+ "type": "int",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ },
+ {
+ "column": {
+ "name": "sergeant_id",
+ "type": "int",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "addUniqueConstraint": {
+ "columnNames": "research_id, sergeant_id",
+ "constraintName": "uc_researches_affected_sergeants_research_id_sergeant_id",
+ "tableName": "researches_affected_sergeants"
+ }
+ },
+ {
+ "addForeignKeyConstraint":
+ {
+ "baseColumnNames": "research_id",
+ "baseTableName": "researches_affected_sergeants",
+ "constraintName": "fk_researches_researches_affected_sergeants",
+ "referencedColumnNames": "id",
+ "referencedTableName": "researches",
+ "onDelete": "CASCADE"
+ }
+ },
+ {
+ "addForeignKeyConstraint":
+ {
+ "baseColumnNames": "sergeant_id",
+ "baseTableName": "researches_affected_sergeants",
+ "constraintName": "fk_sergeants_researches_affected_sergeants",
+ "referencedColumnNames": "id",
+ "referencedTableName": "sergeants",
+ "onDelete": "CASCADE"
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/src/main/resources/db/0.0.3/schema/researches_affected_units.json b/src/main/resources/db/0.0.3/schema/researches_affected_units.json
new file mode 100644
index 0000000..24e9ea3
--- /dev/null
+++ b/src/main/resources/db/0.0.3/schema/researches_affected_units.json
@@ -0,0 +1,66 @@
+{
+ "databaseChangeLog": [
+ {
+ "changeSet": {
+ "id": "Add researches_affected_units table",
+ "author": "anibus",
+ "changes": [
+ {
+ "createTable": {
+ "tableName": "researches_affected_units",
+ "columns": [
+ {
+ "column": {
+ "name": "research_id",
+ "type": "int",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ },
+ {
+ "column": {
+ "name": "unit_id",
+ "type": "int",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "addUniqueConstraint": {
+ "columnNames": "research_id, unit_id",
+ "constraintName": "uc_researches_affected_units_research_id_unit_id",
+ "tableName": "researches_affected_units"
+ }
+ },
+ {
+ "addForeignKeyConstraint":
+ {
+ "baseColumnNames": "research_id",
+ "baseTableName": "researches_affected_units",
+ "constraintName": "fk_researches_researches_affected_units",
+ "referencedColumnNames": "id",
+ "referencedTableName": "researches",
+ "onDelete": "CASCADE"
+ }
+ },
+ {
+ "addForeignKeyConstraint":
+ {
+ "baseColumnNames": "unit_id",
+ "baseTableName": "researches_affected_units",
+ "constraintName": "fk_units_researches_affected_units",
+ "referencedColumnNames": "id",
+ "referencedTableName": "units",
+ "onDelete": "CASCADE"
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/src/main/resources/db/0.0.3/schema/researches_affected_weapons.json b/src/main/resources/db/0.0.3/schema/researches_affected_weapons.json
new file mode 100644
index 0000000..94bb06a
--- /dev/null
+++ b/src/main/resources/db/0.0.3/schema/researches_affected_weapons.json
@@ -0,0 +1,66 @@
+{
+ "databaseChangeLog": [
+ {
+ "changeSet": {
+ "id": "Add researches_affected_weapons table",
+ "author": "anibus",
+ "changes": [
+ {
+ "createTable": {
+ "tableName": "researches_affected_weapons",
+ "columns": [
+ {
+ "column": {
+ "name": "research_id",
+ "type": "int",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ },
+ {
+ "column": {
+ "name": "weapon_id",
+ "type": "int",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "addUniqueConstraint": {
+ "columnNames": "research_id, weapon_id",
+ "constraintName": "uc_researches_affected_weapons_research_id_weapon_id",
+ "tableName": "researches_affected_weapons"
+ }
+ },
+ {
+ "addForeignKeyConstraint":
+ {
+ "baseColumnNames": "research_id",
+ "baseTableName": "researches_affected_weapons",
+ "constraintName": "fk_researches_researches_affected_weapons",
+ "referencedColumnNames": "id",
+ "referencedTableName": "researches",
+ "onDelete": "CASCADE"
+ }
+ },
+ {
+ "addForeignKeyConstraint":
+ {
+ "baseColumnNames": "weapon_id",
+ "baseTableName": "researches_affected_weapons",
+ "constraintName": "fk_weapons_researches_affected_weapons",
+ "referencedColumnNames": "id",
+ "referencedTableName": "weapons",
+ "onDelete": "CASCADE"
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/src/main/resources/db/0.0.3/schema/sergeants.json b/src/main/resources/db/0.0.3/schema/sergeants.json
new file mode 100644
index 0000000..747b811
--- /dev/null
+++ b/src/main/resources/db/0.0.3/schema/sergeants.json
@@ -0,0 +1,25 @@
+{
+ "databaseChangeLog": [
+ {
+ "changeSet": {
+ "id": "Add mod_id column to sergeants",
+ "author": "anibus",
+ "changes": [
+ {
+ "addColumn": {
+ "columns": [
+ {
+ "column": {
+ "name": "mod_id",
+ "type": "int"
+ }
+ }
+ ],
+ "tableName": "sergeants"
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/src/main/resources/db/0.0.3/schema/units.json b/src/main/resources/db/0.0.3/schema/units.json
new file mode 100644
index 0000000..6923e05
--- /dev/null
+++ b/src/main/resources/db/0.0.3/schema/units.json
@@ -0,0 +1,36 @@
+{
+ "databaseChangeLog": [
+ {
+ "changeSet": {
+ "id": "Add filename_unit column to unit and rename filename to filename_squad",
+ "author": "anibus",
+ "changes": [
+ {
+ "addColumn": {
+ "columns": [
+ {
+ "column": {
+ "name": "filename_unit",
+ "type": "varchar(255)",
+ "value": "",
+ "constraints": {
+ "nullable": false
+ }
+ }
+ }
+ ],
+ "tableName": "units"
+ }
+ },
+ {
+ "renameColumn": {
+ "newColumnName": "filename_squad",
+ "oldColumnName": "filename",
+ "tableName": "units"
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/src/main/resources/db/changelog-master.json b/src/main/resources/db/changelog-master.json
index 69dd6b9..34e7ac7 100644
--- a/src/main/resources/db/changelog-master.json
+++ b/src/main/resources/db/changelog-master.json
@@ -107,6 +107,67 @@
"include": {
"file": "db/0.0.2/data/armor_types.json"
}
+ },
+ {
+ "include": {
+ "file": "db/0.0.3/schema/researches.json"
+ }
+ },{
+ "include": {
+ "file": "db/0.0.3/schema/research_requirements.json"
+ }
+ },{
+ "include": {
+ "file": "db/0.0.3/schema/research_modifiers.json"
+ }
+ },{
+ "include": {
+ "file": "db/0.0.3/schema/abilities.json"
+ }
+ },{
+ "include": {
+ "file": "db/0.0.3/schema/buildings_researches.json"
+ }
+ },{
+ "include": {
+ "file": "db/0.0.3/schema/researches_affected_units.json"
+ }
+ },{
+ "include": {
+ "file": "db/0.0.3/schema/researches_affected_sergeants.json"
+ }
+ },{
+ "include": {
+ "file": "db/0.0.3/schema/researches_affected_buildings.json"
+ }
+ },{
+ "include": {
+ "file": "db/0.0.3/schema/researches_affected_weapons.json"
+ }
+ },
+ {
+ "include": {
+ "file": "db/0.0.3/procedures/delete_mod_data_procedure.sql"
+ }
+ },
+ {
+ "include": {
+ "file": "db/0.0.3/schema/units.json"
+ }
+ },
+ {
+ "include": {
+ "file": "db/0.0.3/data/armor_types.json"
+ }
+ },{
+ "include": {
+ "file": "db/0.0.3/procedures/delete_campaign_entities.sql"
+ }
+ },
+ {
+ "include": {
+ "file": "db/0.0.3/schema/sergeants.json"
+ }
}
]
}
diff --git a/src/test/kotlin/com/example/dowstats/service/w40k/BuildingRgdExtractServiceTest.kt b/src/test/kotlin/com/example/dowstats/service/w40k/BuildingRgdExtractServiceTest.kt
index bf94000..bd82683 100644
--- a/src/test/kotlin/com/example/dowstats/service/w40k/BuildingRgdExtractServiceTest.kt
+++ b/src/test/kotlin/com/example/dowstats/service/w40k/BuildingRgdExtractServiceTest.kt
@@ -18,33 +18,6 @@ class BuildingRgdExtractServiceTest {
val iconService = mockk()
val addonRgdExtractService = mockk()
- val buildingRgdExtractService = BuildingRgdExtractService(modAttribPathService, iconService, addonRgdExtractService)
-
val rgdService = RgdParserService()
- @Test
- fun `Should correct parse building`() {
-
- val buildingRgdFile = File("src/test/resources/rgd/waagh_banner/ork_waagh_banner.rgd")
-
- val rgdData = rgdService.parseRgdFileStream(DataInputStream(buildingRgdFile.inputStream()))
-
- val res = buildingRgdExtractService.extractToBuildingEntity("Waagh banner", emptyMap(), rgdData, emptySet(), "orks", "/modFolder", Mod(), listOf(
- Race().also {
- it.id = "orks"
- it.name = "Орки"
- }
- ), listOf(
- ArmorType().also {
- it.id = "building_low"
- it.name = "Лёгкие здания"
- }
- ),
- emptyMap())
-
- assertEquals(170.toDouble(), res.building.buildCostRequisition)
- assertEquals(emptySet(), res.buildingWeapons)
-
- }
-
}
\ No newline at end of file