mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-13 07:24:53 +00:00
accounted for collapsing cert trees, exclusive certifications, and a method of keeping track of certification costs (#227)
This commit is contained in:
parent
2f0629d83a
commit
8b5073dcbc
7 changed files with 449 additions and 61 deletions
|
|
@ -0,0 +1,233 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects.avatar
|
||||||
|
|
||||||
|
import net.psforever.types.CertificationType
|
||||||
|
|
||||||
|
import scala.collection.mutable
|
||||||
|
|
||||||
|
object Certification {
|
||||||
|
object Dependencies {
|
||||||
|
/**
|
||||||
|
* Find the certifications that are immediately dependent on the target certification.
|
||||||
|
* (For `A`, find all `B` that are `B ⇒ A`.)
|
||||||
|
* @param certification the target certification
|
||||||
|
* @return all connected certifications
|
||||||
|
*/
|
||||||
|
def From(certification : CertificationType.Value) : Set[CertificationType.Value] = dependencies(certification).toSet
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all certifications that are dependent on the target certification.
|
||||||
|
* (For `A`, find all `B...C` where `C ⇒ B` and `B ⇒ A`.)
|
||||||
|
* @param certification the target certification
|
||||||
|
* @return all connected certifications
|
||||||
|
*/
|
||||||
|
def FromAll(certification : CertificationType.Value) : Set[CertificationType.Value] = {
|
||||||
|
var available : List[CertificationType.Value] = List(certification)
|
||||||
|
var allocated : mutable.ListBuffer[CertificationType.Value] = mutable.ListBuffer.empty[CertificationType.Value]
|
||||||
|
do {
|
||||||
|
available = available.flatMap(cert => dependencies(cert))
|
||||||
|
allocated ++= available
|
||||||
|
}
|
||||||
|
while(available.nonEmpty)
|
||||||
|
allocated.toSet
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the certifications that are immediate dependencies of the target certification.
|
||||||
|
* (For `A`, find all `B` where `A ⇒ B`.)
|
||||||
|
* @param certification the target certification
|
||||||
|
* @return all connected certifications
|
||||||
|
*/
|
||||||
|
def For(certification : CertificationType.Value) : Set[CertificationType.Value] = {
|
||||||
|
(for {
|
||||||
|
(cert, certs) <- dependencies
|
||||||
|
if certs contains certification
|
||||||
|
} yield cert).toSet
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all certifications that are dependencies of the target certification.
|
||||||
|
* (For `A`, find all `B...C` where `A ⇒ B` and `B ⇒ C`.)
|
||||||
|
* @param certification the target certification
|
||||||
|
* @return all connected certifications
|
||||||
|
*/
|
||||||
|
def ForAll(certification : CertificationType.Value) : Set[CertificationType.Value] = {
|
||||||
|
var available : List[CertificationType.Value] = List(certification)
|
||||||
|
var allocated : mutable.ListBuffer[CertificationType.Value] = mutable.ListBuffer.empty[CertificationType.Value]
|
||||||
|
do {
|
||||||
|
available = available.flatMap {
|
||||||
|
For
|
||||||
|
}
|
||||||
|
allocated ++= available
|
||||||
|
}
|
||||||
|
while(available.nonEmpty)
|
||||||
|
allocated.toSet
|
||||||
|
}
|
||||||
|
|
||||||
|
import CertificationType._
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all certifications that are related but mutually exclusive with the target certification.
|
||||||
|
* (For `A`, find all `B` that `B ⊃ A` but `A XOR B`.)
|
||||||
|
* @param certification the target certification
|
||||||
|
* @return all connected certifications
|
||||||
|
*/
|
||||||
|
def Like(certification : CertificationType.Value) : Set[CertificationType.Value] = certification match {
|
||||||
|
case AssaultBuggy =>
|
||||||
|
Set(Harasser)
|
||||||
|
case LightScout =>
|
||||||
|
Set(AirCavalryScout, AssaultBuggy, Harasser)
|
||||||
|
case UniMAX =>
|
||||||
|
Set(AAMAX, AIMAX, AVMAX)
|
||||||
|
case AdvancedEngineering =>
|
||||||
|
Set(AssaultEngineering, FortificationEngineering)
|
||||||
|
case ElectronicsExpert =>
|
||||||
|
Set(DataCorruption, ExpertHacking)
|
||||||
|
case _ =>
|
||||||
|
Set.empty[CertificationType.Value]
|
||||||
|
}
|
||||||
|
|
||||||
|
private val dependencies : Map[CertificationType.Value, List[CertificationType.Value]] = Map(
|
||||||
|
StandardAssault -> List(),
|
||||||
|
AgileExoSuit -> List(),
|
||||||
|
ReinforcedExoSuit -> List(),
|
||||||
|
InfiltrationSuit -> List(Phantasm),
|
||||||
|
AIMAX -> List(),
|
||||||
|
AVMAX -> List(),
|
||||||
|
AAMAX -> List(),
|
||||||
|
UniMAX -> List(),
|
||||||
|
|
||||||
|
StandardAssault -> List(),
|
||||||
|
MediumAssault -> List(AntiVehicular, HeavyAssault, Sniping, SpecialAssault),
|
||||||
|
AntiVehicular -> List(),
|
||||||
|
HeavyAssault -> List(),
|
||||||
|
Sniping -> List(),
|
||||||
|
SpecialAssault -> List(EliteAssault),
|
||||||
|
EliteAssault -> List(),
|
||||||
|
|
||||||
|
ATV -> List(Switchblade),
|
||||||
|
Switchblade -> List(),
|
||||||
|
Harasser -> List(),
|
||||||
|
AssaultBuggy -> List(),
|
||||||
|
LightScout -> List(AirCavalryAssault),
|
||||||
|
GroundSupport -> List(),
|
||||||
|
GroundTransport -> List(),
|
||||||
|
ArmoredAssault1 -> List(ArmoredAssault2),
|
||||||
|
ArmoredAssault2 -> List(BattleFrameRobotics, Flail),
|
||||||
|
Flail -> List(),
|
||||||
|
|
||||||
|
AirCavalryScout -> List(AirCavalryAssault),
|
||||||
|
AirCavalryAssault -> List(AirCavalryInterceptor),
|
||||||
|
AirCavalryInterceptor -> List(),
|
||||||
|
AirSupport -> List(GalaxyGunship),
|
||||||
|
GalaxyGunship -> List(),
|
||||||
|
Phantasm -> List(),
|
||||||
|
|
||||||
|
BattleFrameRobotics -> List(BFRAntiInfantry, BFRAntiAircraft),
|
||||||
|
BFRAntiInfantry -> List(),
|
||||||
|
BFRAntiAircraft -> List(),
|
||||||
|
|
||||||
|
Medical -> List(AdvancedMedical),
|
||||||
|
AdvancedMedical -> List(),
|
||||||
|
Engineering -> List(CombatEngineering),
|
||||||
|
CombatEngineering -> List(AdvancedEngineering, AssaultEngineering, FortificationEngineering),
|
||||||
|
AdvancedEngineering -> List(),
|
||||||
|
AssaultEngineering -> List(),
|
||||||
|
FortificationEngineering -> List(),
|
||||||
|
Hacking -> List(AdvancedHacking),
|
||||||
|
AdvancedHacking -> List(DataCorruption, ElectronicsExpert, ExpertHacking),
|
||||||
|
DataCorruption -> List(),
|
||||||
|
ElectronicsExpert -> List(),
|
||||||
|
ExpertHacking -> List()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
object Cost {
|
||||||
|
/**
|
||||||
|
* For a certification, get its point cost.
|
||||||
|
* @param certification the certification
|
||||||
|
* @return the cost
|
||||||
|
*/
|
||||||
|
def Of(certification : CertificationType.Value) : Int = points(certification)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For a list of certifications, find the point cost of all unique certifications.
|
||||||
|
* @see `Of(Set)`
|
||||||
|
* @param certifications the certification list
|
||||||
|
* @return the total cost
|
||||||
|
*/
|
||||||
|
def Of(certifications : List[CertificationType.Value]) : Int = Of(certifications.toSet)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For a set of certifications, find the point cost of all certifications.
|
||||||
|
* @see `OfAll(List)`
|
||||||
|
* @param certifications the certification list
|
||||||
|
* @return the total cost
|
||||||
|
*/
|
||||||
|
def Of(certifications : Set[CertificationType.Value]) : Int = OfAll(certifications.toList)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For a list of certifications, find the point cost of all certifications, counting any duplicates.
|
||||||
|
* @param certifications the certification list
|
||||||
|
* @return the total cost
|
||||||
|
*/
|
||||||
|
def OfAll(certifications : List[CertificationType.Value]) : Int = {
|
||||||
|
certifications map points sum
|
||||||
|
}
|
||||||
|
|
||||||
|
import CertificationType._
|
||||||
|
private val points : Map[CertificationType.Value, Int] = Map(
|
||||||
|
StandardExoSuit -> 0,
|
||||||
|
AgileExoSuit -> 0,
|
||||||
|
ReinforcedExoSuit -> 3,
|
||||||
|
InfiltrationSuit -> 2,
|
||||||
|
AAMAX -> 2,
|
||||||
|
AIMAX -> 3,
|
||||||
|
AVMAX -> 3,
|
||||||
|
UniMAX -> 6,
|
||||||
|
|
||||||
|
StandardAssault -> 0,
|
||||||
|
MediumAssault -> 2,
|
||||||
|
AntiVehicular -> 3,
|
||||||
|
HeavyAssault -> 4,
|
||||||
|
Sniping -> 3,
|
||||||
|
SpecialAssault -> 3,
|
||||||
|
EliteAssault -> 1,
|
||||||
|
|
||||||
|
ATV -> 1,
|
||||||
|
Switchblade -> 1,
|
||||||
|
Harasser -> 1,
|
||||||
|
AssaultBuggy -> 3,
|
||||||
|
LightScout -> 5,
|
||||||
|
GroundSupport -> 2,
|
||||||
|
GroundTransport -> 2,
|
||||||
|
ArmoredAssault1 -> 2,
|
||||||
|
ArmoredAssault2 -> 3,
|
||||||
|
Flail -> 1,
|
||||||
|
|
||||||
|
AirCavalryScout -> 3,
|
||||||
|
AirCavalryAssault -> 2,
|
||||||
|
AirCavalryInterceptor -> 2,
|
||||||
|
AirSupport -> 3,
|
||||||
|
GalaxyGunship -> 2,
|
||||||
|
Phantasm -> 3,
|
||||||
|
|
||||||
|
BattleFrameRobotics -> 4,
|
||||||
|
BFRAntiInfantry -> 1,
|
||||||
|
BFRAntiAircraft -> 1,
|
||||||
|
|
||||||
|
Medical -> 3,
|
||||||
|
AdvancedMedical -> 2,
|
||||||
|
Engineering -> 3,
|
||||||
|
CombatEngineering -> 2,
|
||||||
|
AdvancedEngineering -> 5,
|
||||||
|
AssaultEngineering -> 3,
|
||||||
|
FortificationEngineering -> 3,
|
||||||
|
Hacking -> 3,
|
||||||
|
AdvancedHacking -> 2,
|
||||||
|
DataCorruption -> 3,
|
||||||
|
ElectronicsExpert -> 4,
|
||||||
|
ExpertHacking -> 2
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,47 +16,47 @@ class CertTerminalDefinition extends TerminalDefinition(171) {
|
||||||
* The certifications available.
|
* The certifications available.
|
||||||
* All entries are listed on page (tab) number 0.
|
* All entries are listed on page (tab) number 0.
|
||||||
*/
|
*/
|
||||||
private val certificationList : Map[String, (CertificationType.Value, Int)] = Map(
|
private val certificationList : Map[String, CertificationType.Value] = Map(
|
||||||
"medium_assault" -> (CertificationType.MediumAssault, 2),
|
"medium_assault" -> CertificationType.MediumAssault,
|
||||||
"reinforced_armor" -> (CertificationType.ReinforcedExoSuit, 3),
|
"reinforced_armor" -> CertificationType.ReinforcedExoSuit,
|
||||||
"quad_all" -> (CertificationType.ATV, 1),
|
"quad_all" -> CertificationType.ATV,
|
||||||
"switchblade" -> (CertificationType.Switchblade, 1),
|
"switchblade" -> CertificationType.Switchblade,
|
||||||
"harasser" -> (CertificationType.Harasser, 1),
|
"harasser" -> CertificationType.Harasser,
|
||||||
"anti_vehicular" -> (CertificationType.AntiVehicular, 3),
|
"anti_vehicular" -> CertificationType.AntiVehicular,
|
||||||
"heavy_assault" -> (CertificationType.HeavyAssault, 4),
|
"heavy_assault" -> CertificationType.HeavyAssault,
|
||||||
"sniper" -> (CertificationType.Sniping, 3),
|
"sniper" -> CertificationType.Sniping,
|
||||||
"special_assault" -> (CertificationType.SpecialAssault, 3),
|
"special_assault" -> CertificationType.SpecialAssault,
|
||||||
"special_assault_2" -> (CertificationType.EliteAssault, 1),
|
"special_assault_2" -> CertificationType.EliteAssault,
|
||||||
"infiltration_suit" -> (CertificationType.InfiltrationSuit, 2),
|
"infiltration_suit" -> CertificationType.InfiltrationSuit,
|
||||||
"max_anti_personnel" -> (CertificationType.AIMAX, 3),
|
"max_anti_personnel" -> CertificationType.AIMAX,
|
||||||
"max_anti_vehicular" -> (CertificationType.AVMAX, 3),
|
"max_anti_vehicular" -> CertificationType.AVMAX,
|
||||||
"max_anti_aircraft" -> (CertificationType.AAMAX, 2),
|
"max_anti_aircraft" -> CertificationType.AAMAX,
|
||||||
"max_all" -> (CertificationType.UniMAX, 6),
|
"max_all" -> CertificationType.UniMAX,
|
||||||
"air_cavalry_scout" -> (CertificationType.AirCavalryScout, 3),
|
"air_cavalry_scout" -> CertificationType.AirCavalryScout,
|
||||||
"air_cavalry_assault" -> (CertificationType.AirCavalryAssault, 2),
|
"air_cavalry_assault" -> CertificationType.AirCavalryAssault,
|
||||||
"air_cavalry_interceptor" -> (CertificationType.AirCavalryInterceptor, 2),
|
"air_cavalry_interceptor" -> CertificationType.AirCavalryInterceptor,
|
||||||
"air_support" -> (CertificationType.AirSupport, 3),
|
"air_support" -> CertificationType.AirSupport,
|
||||||
"gunship" -> (CertificationType.GalaxyGunship, 2),
|
"gunship" -> CertificationType.GalaxyGunship,
|
||||||
"phantasm" -> (CertificationType.Phantasm, 3),
|
"phantasm" -> CertificationType.Phantasm,
|
||||||
"armored_assault1" -> (CertificationType.ArmoredAssault1, 2),
|
"armored_assault1" -> CertificationType.ArmoredAssault1,
|
||||||
"armored_assault2" -> (CertificationType.ArmoredAssault2, 1),
|
"armored_assault2" -> CertificationType.ArmoredAssault2,
|
||||||
"flail" -> (CertificationType.Flail, 1),
|
"flail" -> CertificationType.Flail,
|
||||||
"assault_buggy" -> (CertificationType.AssaultBuggy, 3),
|
"assault_buggy" -> CertificationType.AssaultBuggy,
|
||||||
"ground_support" -> (CertificationType.GroundSupport, 2),
|
"ground_support" -> CertificationType.GroundSupport,
|
||||||
"ground_transport" -> (CertificationType.GroundTransport, 2),
|
"ground_transport" -> CertificationType.GroundTransport,
|
||||||
"light_scout" -> (CertificationType.LightScout, 5),
|
"light_scout" -> CertificationType.LightScout,
|
||||||
"Repair" -> (CertificationType.Engineering, 3),
|
"Repair" -> CertificationType.Engineering,
|
||||||
"combat_engineering" -> (CertificationType.CombatEngineering, 2),
|
"combat_engineering" -> CertificationType.CombatEngineering,
|
||||||
"ce_offense" -> (CertificationType.AssaultEngineering, 3),
|
"ce_offense" -> CertificationType.AssaultEngineering,
|
||||||
"ce_defense" -> (CertificationType.FortificationEngineering, 3),
|
"ce_defense" -> CertificationType.FortificationEngineering,
|
||||||
"ce_advanced" -> (CertificationType.AdvancedEngineering, 5),
|
"ce_advanced" -> CertificationType.AdvancedEngineering,
|
||||||
"Hacking" -> (CertificationType.Hacking, 3),
|
"Hacking" -> CertificationType.Hacking,
|
||||||
"advanced_hacking" -> (CertificationType.AdvancedHacking, 2),
|
"advanced_hacking" -> CertificationType.AdvancedHacking,
|
||||||
"expert_hacking" -> (CertificationType.ExpertHacking, 2),
|
"expert_hacking" -> CertificationType.ExpertHacking,
|
||||||
"virus_hacking" -> (CertificationType.DataCorruption, 3),
|
"virus_hacking" -> CertificationType.DataCorruption,
|
||||||
"electronics_expert" -> (CertificationType.ElectronicsExpert, 4),
|
"electronics_expert" -> CertificationType.ElectronicsExpert,
|
||||||
"Medical" -> (CertificationType.Medical, 3),
|
"Medical" -> CertificationType.Medical,
|
||||||
"advanced_medical" -> (CertificationType.AdvancedMedical, 2)
|
"advanced_medical" -> CertificationType.AdvancedMedical
|
||||||
//TODO bfr certification entries
|
//TODO bfr certification entries
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -68,8 +68,8 @@ class CertTerminalDefinition extends TerminalDefinition(171) {
|
||||||
*/
|
*/
|
||||||
def Buy(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = { //Learn
|
def Buy(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = { //Learn
|
||||||
certificationList.get(msg.item_name) match {
|
certificationList.get(msg.item_name) match {
|
||||||
case Some((cert, cost)) =>
|
case Some(cert) =>
|
||||||
Terminal.LearnCertification(cert, cost)
|
Terminal.LearnCertification(cert)
|
||||||
case None =>
|
case None =>
|
||||||
Terminal.NoDeal()
|
Terminal.NoDeal()
|
||||||
}
|
}
|
||||||
|
|
@ -83,8 +83,8 @@ class CertTerminalDefinition extends TerminalDefinition(171) {
|
||||||
*/
|
*/
|
||||||
override def Sell(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
|
override def Sell(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
|
||||||
certificationList.get(msg.item_name) match {
|
certificationList.get(msg.item_name) match {
|
||||||
case Some((cert, cost)) =>
|
case Some(cert) =>
|
||||||
Terminal.SellCertification(cert, cost)
|
Terminal.SellCertification(cert)
|
||||||
case None =>
|
case None =>
|
||||||
Terminal.NoDeal()
|
Terminal.NoDeal()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -116,16 +116,14 @@ object Terminal {
|
||||||
/**
|
/**
|
||||||
* Provide the certification type unlocked by the player.
|
* Provide the certification type unlocked by the player.
|
||||||
* @param cert the certification unlocked
|
* @param cert the certification unlocked
|
||||||
* @param cost the certification point cost
|
|
||||||
*/
|
*/
|
||||||
final case class LearnCertification(cert : CertificationType.Value, cost : Int) extends Exchange
|
final case class LearnCertification(cert : CertificationType.Value) extends Exchange
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide the certification type freed-up by the player.
|
* Provide the certification type freed-up by the player.
|
||||||
* @param cert the certification returned
|
* @param cert the certification returned
|
||||||
* @param cost the certification point cost
|
|
||||||
*/
|
*/
|
||||||
final case class SellCertification(cert : CertificationType.Value, cost : Int) extends Exchange
|
final case class SellCertification(cert : CertificationType.Value) extends Exchange
|
||||||
|
|
||||||
import net.psforever.objects.definition.ImplantDefinition
|
import net.psforever.objects.definition.ImplantDefinition
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
140
common/src/test/scala/objects/CertificationTest.scala
Normal file
140
common/src/test/scala/objects/CertificationTest.scala
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package objects
|
||||||
|
|
||||||
|
import net.psforever.objects.avatar.Certification
|
||||||
|
import net.psforever.types.CertificationType._
|
||||||
|
import org.specs2.mutable.Specification
|
||||||
|
|
||||||
|
class CertificationTest extends Specification {
|
||||||
|
"Dependencies" should {
|
||||||
|
//From
|
||||||
|
"find any certifications immediately dependent on a given certification (nothing)" in {
|
||||||
|
Certification.Dependencies.From(StandardAssault) mustEqual Set()
|
||||||
|
}
|
||||||
|
|
||||||
|
"find any certifications immediately dependent on a given certification (one)" in {
|
||||||
|
Certification.Dependencies.From(Engineering) mustEqual Set(CombatEngineering)
|
||||||
|
}
|
||||||
|
|
||||||
|
"find any certifications immediately dependent on a given certification (multiple)" in {
|
||||||
|
Certification.Dependencies.From(MediumAssault) mustEqual Set(AntiVehicular, HeavyAssault, Sniping, SpecialAssault)
|
||||||
|
}
|
||||||
|
|
||||||
|
"find any certifications immediately dependent on a given certification (intermediate)" in {
|
||||||
|
Certification.Dependencies.From(ArmoredAssault2) mustEqual Set(BattleFrameRobotics, Flail)
|
||||||
|
}
|
||||||
|
//FromAll
|
||||||
|
"find all certifications dependent on a given certification (nothing)" in {
|
||||||
|
Certification.Dependencies.FromAll(StandardAssault) mustEqual Set()
|
||||||
|
}
|
||||||
|
|
||||||
|
"find all certifications dependent on a given certification (one)" in {
|
||||||
|
Certification.Dependencies.FromAll(ATV) mustEqual Set(Switchblade)
|
||||||
|
}
|
||||||
|
|
||||||
|
"find all certifications dependent on a given certification (multiple)" in {
|
||||||
|
Certification.Dependencies.FromAll(MediumAssault) mustEqual Set(AntiVehicular, HeavyAssault, Sniping, SpecialAssault, EliteAssault)
|
||||||
|
}
|
||||||
|
|
||||||
|
"find all certifications dependent on a given certification (intermediate)" in {
|
||||||
|
Certification.Dependencies.FromAll(ArmoredAssault2) mustEqual Set(BattleFrameRobotics, Flail, BFRAntiInfantry, BFRAntiAircraft)
|
||||||
|
}
|
||||||
|
//For
|
||||||
|
"find any certifications that are immediate dependencies for a given certification (nothing)" in {
|
||||||
|
Certification.Dependencies.For(StandardAssault) mustEqual Set()
|
||||||
|
}
|
||||||
|
|
||||||
|
"find any certifications that are immediate dependencies for a given certification (one)" in {
|
||||||
|
Certification.Dependencies.For(CombatEngineering) mustEqual Set(Engineering)
|
||||||
|
}
|
||||||
|
|
||||||
|
"find any certifications that are immediate dependencies for a given certification (multiple)" in {
|
||||||
|
Certification.Dependencies.For(AirCavalryAssault) mustEqual Set(AirCavalryScout, LightScout)
|
||||||
|
}
|
||||||
|
|
||||||
|
"find any certifications that are immediate dependencies for a given certification (intermediate)" in {
|
||||||
|
Certification.Dependencies.For(BattleFrameRobotics) mustEqual Set(ArmoredAssault2)
|
||||||
|
}
|
||||||
|
//ForAll
|
||||||
|
"find all certifications that are dependencies for a given certification (nothing)" in {
|
||||||
|
Certification.Dependencies.ForAll(StandardAssault) mustEqual Set()
|
||||||
|
}
|
||||||
|
|
||||||
|
"find all certifications that are dependencies for a given certification (one)" in {
|
||||||
|
Certification.Dependencies.ForAll(CombatEngineering) mustEqual Set(Engineering)
|
||||||
|
}
|
||||||
|
|
||||||
|
"find all certifications that are dependencies for a given certification (multiple)" in {
|
||||||
|
Certification.Dependencies.ForAll(AirCavalryAssault) mustEqual Set(AirCavalryScout, LightScout)
|
||||||
|
}
|
||||||
|
|
||||||
|
"find all certifications that are dependencies for a given certification (intermediate)" in {
|
||||||
|
Certification.Dependencies.ForAll(BattleFrameRobotics) mustEqual Set(ArmoredAssault1, ArmoredAssault2)
|
||||||
|
}
|
||||||
|
//Like
|
||||||
|
"find related certifications" in {
|
||||||
|
Certification.Dependencies.Like(AssaultBuggy) mustEqual Set(Harasser)
|
||||||
|
Certification.Dependencies.Like(LightScout) mustEqual Set(AirCavalryScout, AssaultBuggy, Harasser)
|
||||||
|
Certification.Dependencies.Like(UniMAX) mustEqual Set(AIMAX, AVMAX, AAMAX)
|
||||||
|
Certification.Dependencies.Like(StandardAssault) mustEqual Set()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"Cost" should {
|
||||||
|
"calculate the point-value of any certification (no value)" in {
|
||||||
|
Certification.Cost.Of(StandardAssault) mustEqual 0
|
||||||
|
}
|
||||||
|
|
||||||
|
"calculate the point-value of any certification (value)" in {
|
||||||
|
Certification.Cost.Of(MediumAssault) mustEqual 2
|
||||||
|
}
|
||||||
|
|
||||||
|
"calculate the sum-point-value of all certifications (no value)" in {
|
||||||
|
Certification.Cost.Of(Set(StandardAssault)) mustEqual 0
|
||||||
|
}
|
||||||
|
|
||||||
|
"calculate the sum-point-value of all certifications (value)" in {
|
||||||
|
Certification.Cost.Of(Set(MediumAssault)) mustEqual 2
|
||||||
|
}
|
||||||
|
|
||||||
|
"calculate the sum-point-value of all certifications (add)" in {
|
||||||
|
Certification.Cost.Of(Set(StandardAssault, MediumAssault)) mustEqual 2
|
||||||
|
Certification.Cost.Of(Set(HeavyAssault, MediumAssault)) mustEqual 6
|
||||||
|
}
|
||||||
|
|
||||||
|
"calculate the sum-point-value of all certifications (large collection)" in {
|
||||||
|
Certification.Cost.Of(Set(StandardAssault, MediumAssault, StandardExoSuit, AgileExoSuit, ReinforcedExoSuit, ATV, Harasser)) mustEqual 7
|
||||||
|
}
|
||||||
|
|
||||||
|
"calculate the sum-point-value of all unique certifications (no value)" in {
|
||||||
|
Certification.Cost.Of(List(StandardAssault, StandardAssault)) mustEqual 0
|
||||||
|
}
|
||||||
|
|
||||||
|
"calculate the sum-point-value of all unique certifications (value)" in {
|
||||||
|
Certification.Cost.Of(List(MediumAssault, MediumAssault)) mustEqual 2
|
||||||
|
}
|
||||||
|
|
||||||
|
"calculate the sum-point-value of all unique certifications (add)" in {
|
||||||
|
Certification.Cost.Of(List(StandardAssault, MediumAssault, MediumAssault)) mustEqual 2
|
||||||
|
Certification.Cost.Of(List(HeavyAssault, MediumAssault, HeavyAssault)) mustEqual 6
|
||||||
|
}
|
||||||
|
|
||||||
|
"calculate the sum-point-value of all unique certifications (large collection)" in {
|
||||||
|
Certification.Cost.Of(
|
||||||
|
List(
|
||||||
|
StandardAssault, MediumAssault, StandardExoSuit, AgileExoSuit, ReinforcedExoSuit, ATV, Harasser,
|
||||||
|
MediumAssault, StandardExoSuit, ReinforcedExoSuit, ATV
|
||||||
|
)
|
||||||
|
) mustEqual 7
|
||||||
|
}
|
||||||
|
|
||||||
|
"calculate the sum-point-value of all certifications (count duplicates)" in {
|
||||||
|
Certification.Cost.OfAll(
|
||||||
|
List(
|
||||||
|
StandardAssault, MediumAssault, StandardExoSuit, AgileExoSuit, ReinforcedExoSuit, ATV, Harasser,
|
||||||
|
MediumAssault, StandardExoSuit, ReinforcedExoSuit, ATV
|
||||||
|
)
|
||||||
|
) mustEqual 13
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,7 +24,7 @@ class CertTerminalTest extends Specification {
|
||||||
|
|
||||||
"player can learn a certification ('medium_assault')" in {
|
"player can learn a certification ('medium_assault')" in {
|
||||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Learn, 0, "medium_assault", 0, PlanetSideGUID(0))
|
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Learn, 0, "medium_assault", 0, PlanetSideGUID(0))
|
||||||
terminal.Request(player, msg) mustEqual Terminal.LearnCertification(CertificationType.MediumAssault, 2)
|
terminal.Request(player, msg) mustEqual Terminal.LearnCertification(CertificationType.MediumAssault)
|
||||||
}
|
}
|
||||||
|
|
||||||
"player can not learn a fake certification ('juggling')" in {
|
"player can not learn a fake certification ('juggling')" in {
|
||||||
|
|
@ -36,7 +36,7 @@ class CertTerminalTest extends Specification {
|
||||||
"player can forget a certification ('medium_assault')" in {
|
"player can forget a certification ('medium_assault')" in {
|
||||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Sell, 0, "medium_assault", 0, PlanetSideGUID(0))
|
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Sell, 0, "medium_assault", 0, PlanetSideGUID(0))
|
||||||
|
|
||||||
terminal.Request(player, msg) mustEqual Terminal.SellCertification(CertificationType.MediumAssault, 2)
|
terminal.Request(player, msg) mustEqual Terminal.SellCertification(CertificationType.MediumAssault)
|
||||||
}
|
}
|
||||||
|
|
||||||
"player can not forget a fake certification ('juggling')" in {
|
"player can not forget a fake certification ('juggling')" in {
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ class CertTerminalControl1Test extends ActorTest {
|
||||||
val reply2 = reply.asInstanceOf[Terminal.TerminalMessage]
|
val reply2 = reply.asInstanceOf[Terminal.TerminalMessage]
|
||||||
assert(reply2.player == player)
|
assert(reply2.player == player)
|
||||||
assert(reply2.msg == msg)
|
assert(reply2.msg == msg)
|
||||||
assert(reply2.response == Terminal.LearnCertification(CertificationType.MediumAssault, 2))
|
assert(reply2.response == Terminal.LearnCertification(CertificationType.MediumAssault))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,7 +73,7 @@ class CertTerminalControl3Test extends ActorTest {
|
||||||
val reply2 = reply.asInstanceOf[Terminal.TerminalMessage]
|
val reply2 = reply.asInstanceOf[Terminal.TerminalMessage]
|
||||||
assert(reply2.player == player)
|
assert(reply2.player == player)
|
||||||
assert(reply2.msg == msg)
|
assert(reply2.msg == msg)
|
||||||
assert(reply2.response == Terminal.SellCertification(CertificationType.MediumAssault, 2))
|
assert(reply2.response == Terminal.SellCertification(CertificationType.MediumAssault))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import csr.{CSRWarp, CSRZone, Traveler}
|
||||||
import net.psforever.objects.GlobalDefinitions._
|
import net.psforever.objects.GlobalDefinitions._
|
||||||
import services.ServiceManager.Lookup
|
import services.ServiceManager.Lookup
|
||||||
import net.psforever.objects._
|
import net.psforever.objects._
|
||||||
|
import net.psforever.objects.avatar.Certification
|
||||||
import net.psforever.objects.ballistics._
|
import net.psforever.objects.ballistics._
|
||||||
import net.psforever.objects.definition.ToolDefinition
|
import net.psforever.objects.definition.ToolDefinition
|
||||||
import net.psforever.objects.definition.converter.{CorpseConverter, DestroyedVehicleConverter}
|
import net.psforever.objects.definition.converter.{CorpseConverter, DestroyedVehicleConverter}
|
||||||
|
|
@ -1180,27 +1181,43 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
sendResponse(ItemTransactionResultMessage (msg.terminal_guid, TransactionType.Loadout, false))
|
sendResponse(ItemTransactionResultMessage (msg.terminal_guid, TransactionType.Loadout, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
case Terminal.LearnCertification(cert, cost) =>
|
case Terminal.LearnCertification(cert) =>
|
||||||
|
val name = tplayer.Name
|
||||||
if(!tplayer.Certifications.contains(cert)) {
|
if(!tplayer.Certifications.contains(cert)) {
|
||||||
log.info(s"$tplayer is learning the $cert certification for $cost points")
|
val guid = tplayer.GUID
|
||||||
|
log.info(s"$name is learning the $cert certification for ${Certification.Cost.Of(cert)} points")
|
||||||
avatar.Certifications += cert
|
avatar.Certifications += cert
|
||||||
sendResponse(PlanetsideAttributeMessage(tplayer.GUID, 24, cert.id))
|
sendResponse(PlanetsideAttributeMessage(guid, 24, cert.id.toLong))
|
||||||
|
|
||||||
|
tplayer.Certifications.intersect(Certification.Dependencies.Like(cert)).foreach(entry => {
|
||||||
|
log.info(s"$cert replaces the learned certification $entry that cost ${Certification.Cost.Of(entry)} points")
|
||||||
|
avatar.Certifications -= entry
|
||||||
|
sendResponse(PlanetsideAttributeMessage(guid, 25, entry.id.toLong))
|
||||||
|
})
|
||||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Learn, true))
|
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Learn, true))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.warn(s"$tplayer already knows the $cert certification, so he can't learn it")
|
log.warn(s"$name already knows the $cert certification, so he can't learn it")
|
||||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Learn, false))
|
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Learn, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
case Terminal.SellCertification(cert, cost) =>
|
case Terminal.SellCertification(cert) =>
|
||||||
|
val name = tplayer.Name
|
||||||
if(tplayer.Certifications.contains(cert)) {
|
if(tplayer.Certifications.contains(cert)) {
|
||||||
log.info(s"$tplayer is forgetting the $cert certification for $cost points")
|
val guid = tplayer.GUID
|
||||||
|
log.info(s"$name is forgetting the $cert certification for ${Certification.Cost.Of(cert)} points")
|
||||||
avatar.Certifications -= cert
|
avatar.Certifications -= cert
|
||||||
sendResponse(PlanetsideAttributeMessage(tplayer.GUID, 25, cert.id))
|
sendResponse(PlanetsideAttributeMessage(guid, 25, cert.id.toLong))
|
||||||
|
|
||||||
|
tplayer.Certifications.intersect(Certification.Dependencies.FromAll(cert)).foreach(entry => {
|
||||||
|
log.info(s"$name is also forgetting the ${Certification.Cost.Of(entry)}-point $entry certification which depends on $cert")
|
||||||
|
avatar.Certifications -= entry
|
||||||
|
sendResponse(PlanetsideAttributeMessage(guid, 25, entry.id.toLong))
|
||||||
|
})
|
||||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Sell, true))
|
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Sell, true))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.warn(s"$tplayer doesn't know what a $cert certification is, so he can't forget it")
|
log.warn(s"$name doesn't know what a $cert certification is, so he can't forget it")
|
||||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Learn, false))
|
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Learn, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue