mirror of
https://github.com/arcan1s/ffxivbis.git
synced 2025-07-15 22:59:58 +00:00
more tests
This commit is contained in:
@ -11,8 +11,7 @@ package me.arcanis.ffxivbis.http
|
||||
import akka.actor.ActorRef
|
||||
import akka.pattern.ask
|
||||
import akka.util.Timeout
|
||||
import me.arcanis.ffxivbis.models.{Player, PlayerId}
|
||||
import me.arcanis.ffxivbis.service.Party
|
||||
import me.arcanis.ffxivbis.models.{Party, Player, PlayerId}
|
||||
import me.arcanis.ffxivbis.service.impl.{DatabaseBiSHandler, DatabasePartyHandler}
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
@ -15,7 +15,7 @@ case class PieceResponse(
|
||||
@Schema(description = "is piece tome gear", required = true) isTome: Boolean,
|
||||
@Schema(description = "job name to which piece belong or AnyJob", required = true, example = "DNC") job: String,
|
||||
@Schema(description = "piece name", required = true, example = "body") piece: String) {
|
||||
def toPiece: Piece = Piece(piece, isTome, Job.fromString(job))
|
||||
def toPiece: Piece = Piece(piece, isTome, Job.withName(job))
|
||||
}
|
||||
|
||||
object PieceResponse {
|
||||
|
@ -16,5 +16,5 @@ case class PlayerIdResponse(
|
||||
@Schema(description = "job name", required = true, example = "DNC") job: String,
|
||||
@Schema(description = "player nick name", required = true, example = "Siuan Sanche") nick: String) {
|
||||
def withPartyId(partyId: String): PlayerId =
|
||||
PlayerId(partyId, Job.fromString(job), nick)
|
||||
PlayerId(partyId, Job.withName(job), nick)
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ case class PlayerResponse(
|
||||
@Schema(description = "link to best in slot", example = "https://ffxiv.ariyala.com/19V5R") link: Option[String],
|
||||
@Schema(description = "player loot priority") priority: Option[Int]) {
|
||||
def toPlayer: Player =
|
||||
Player(partyId, Job.fromString(job), nick,
|
||||
Player(partyId, Job.withName(job), nick,
|
||||
BiS(bis.getOrElse(Seq.empty).map(_.toPiece)), loot.getOrElse(Seq.empty).map(_.toPiece),
|
||||
link, priority.getOrElse(0))
|
||||
}
|
||||
|
@ -14,8 +14,7 @@ import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server._
|
||||
import akka.util.Timeout
|
||||
import me.arcanis.ffxivbis.http.UserHelper
|
||||
import me.arcanis.ffxivbis.models.{Permission, User}
|
||||
import me.arcanis.ffxivbis.service.Party
|
||||
import me.arcanis.ffxivbis.models.{Party, Permission, User}
|
||||
|
||||
class IndexView(storage: ActorRef)(implicit timeout: Timeout)
|
||||
extends UserHelper(storage) {
|
||||
|
@ -92,7 +92,7 @@ object PlayerView {
|
||||
form(action:=s"/party/$partyId/players", method:="post")(
|
||||
input(name:="nick", id:="nick", placeholder:="nick", title:="nick", `type`:="nick"),
|
||||
select(name:="job", id:="job", title:="job")
|
||||
(for (job <- Job.groupAll) yield option(job.toString)),
|
||||
(for (job <- Job.jobs) yield option(job.toString)),
|
||||
input(name:="link", id:="link", placeholder:="player bis link", title:="link", `type`:="text"),
|
||||
input(name:="prioiry", id:="priority", placeholder:="priority", title:="priority", `type`:="number", value:="0"),
|
||||
input(name:="action", id:="action", `type`:="hidden", value:="add"),
|
||||
|
@ -76,5 +76,5 @@ object BiS {
|
||||
def apply(): BiS = BiS(Seq.empty)
|
||||
|
||||
def apply(pieces: Seq[Piece]): BiS =
|
||||
BiS(pieces.map { piece => piece.piece -> Some(piece) }.toMap)
|
||||
BiS(pieces.map(piece => piece.piece -> Some(piece)).toMap)
|
||||
}
|
||||
|
@ -9,65 +9,95 @@
|
||||
package me.arcanis.ffxivbis.models
|
||||
|
||||
object Job {
|
||||
sealed trait Job
|
||||
sealed trait RightSide
|
||||
object AccessoriesDex extends RightSide
|
||||
object AccessoriesInt extends RightSide
|
||||
object AccessoriesMnd extends RightSide
|
||||
object AccessoriesStr extends RightSide
|
||||
object AccessoriesVit extends RightSide
|
||||
|
||||
sealed trait LeftSide
|
||||
object BodyCasters extends LeftSide
|
||||
object BodyDrgs extends LeftSide
|
||||
object BodyHealers extends LeftSide
|
||||
object BodyMnks extends LeftSide
|
||||
object BodyNins extends LeftSide
|
||||
object BodyTanks extends LeftSide
|
||||
object BodyRanges extends LeftSide
|
||||
|
||||
sealed trait Job {
|
||||
def leftSide: LeftSide
|
||||
def rightSide: RightSide
|
||||
|
||||
// conversion to string to avoid recursion
|
||||
override def equals(obj: Any): Boolean = {
|
||||
def canEqual(obj: Any): Boolean = obj.isInstanceOf[Job]
|
||||
def equality(objRepr: String): Boolean = objRepr match {
|
||||
case _ if objRepr == AnyJob.toString => true
|
||||
case _ if this.toString == AnyJob.toString => true
|
||||
case _ => this.toString == obj.toString
|
||||
}
|
||||
|
||||
canEqual(obj) && equality(obj.toString)
|
||||
}
|
||||
}
|
||||
|
||||
case object AnyJob extends Job {
|
||||
override def equals(obj: Any): Boolean = obj match {
|
||||
case Job => true
|
||||
case _ => false
|
||||
}
|
||||
val leftSide: LeftSide = null
|
||||
val rightSide: RightSide = null
|
||||
}
|
||||
|
||||
case object PLD extends Job
|
||||
case object WAR extends Job
|
||||
case object DRK extends Job
|
||||
case object GNB extends Job
|
||||
|
||||
case object WHM extends Job
|
||||
case object SCH extends Job
|
||||
case object AST extends Job
|
||||
|
||||
case object MNK extends Job
|
||||
case object DRG extends Job
|
||||
case object NIN extends Job
|
||||
case object SAM extends Job
|
||||
|
||||
case object BRD extends Job
|
||||
case object MCH extends Job
|
||||
case object DNC extends Job
|
||||
|
||||
case object BLM extends Job
|
||||
case object SMN extends Job
|
||||
case object RDM extends Job
|
||||
|
||||
def groupAccessoriesDex: Seq[Job.Job] = groupRanges :+ NIN
|
||||
def groupAccessoriesStr: Seq[Job.Job] = groupMnk :+ DRG
|
||||
def groupAll: Seq[Job.Job] = groupCasters ++ groupHealers ++ groupRanges ++ groupTanks
|
||||
def groupCasters: Seq[Job.Job] = Seq(BLM, SMN, RDM)
|
||||
def groupHealers: Seq[Job.Job] = Seq(WHM, SCH, AST)
|
||||
def groupMnk: Seq[Job.Job] = Seq(MNK, SAM)
|
||||
def groupRanges: Seq[Job.Job] = Seq(BRD, MCH, DNC)
|
||||
def groupTanks: Seq[Job.Job] = Seq(PLD, WAR, DRK, GNB)
|
||||
|
||||
def groupFull: Seq[Seq[Job.Job]] = Seq(groupCasters, groupHealers, groupMnk, groupRanges, groupTanks)
|
||||
def groupRight: Seq[Seq[Job.Job]] = Seq(groupAccessoriesDex, groupAccessoriesStr)
|
||||
|
||||
def fromString(job: String): Job.Job = groupAll.find(_.toString == job.toUpperCase).orNull
|
||||
|
||||
def hasSameLoot(left: Job, right: Job, piece: Piece): Boolean = {
|
||||
def isAccessory(piece: Piece): Boolean = piece match {
|
||||
case _: PieceAccessory => true
|
||||
case _ => false
|
||||
}
|
||||
def isWeapon(piece: Piece): Boolean = piece match {
|
||||
case _: PieceWeapon => true
|
||||
case _ => false
|
||||
}
|
||||
|
||||
if (left == right) true
|
||||
else if (isWeapon(piece)) false
|
||||
else if (groupFull.exists(group => group.contains(left) && group.contains(right))) true
|
||||
else if (isAccessory(piece) && groupRight.exists(group => group.contains(left) && group.contains(right))) true
|
||||
else false
|
||||
trait Casters extends Job {
|
||||
val leftSide: LeftSide = BodyCasters
|
||||
val rightSide: RightSide = AccessoriesInt
|
||||
}
|
||||
trait Healers extends Job {
|
||||
val leftSide: LeftSide = BodyHealers
|
||||
val rightSide: RightSide = AccessoriesMnd
|
||||
}
|
||||
trait Mnks extends Job {
|
||||
val leftSide: LeftSide = BodyMnks
|
||||
val rightSide: RightSide = AccessoriesStr
|
||||
}
|
||||
trait Tanks extends Job {
|
||||
val leftSide: LeftSide = BodyTanks
|
||||
val rightSide: RightSide = AccessoriesVit
|
||||
}
|
||||
trait Ranges extends Job {
|
||||
val leftSide: LeftSide = BodyRanges
|
||||
val rightSide: RightSide = AccessoriesDex
|
||||
}
|
||||
|
||||
case object PLD extends Tanks
|
||||
case object WAR extends Tanks
|
||||
case object DRK extends Tanks
|
||||
case object GNB extends Tanks
|
||||
|
||||
case object WHM extends Healers
|
||||
case object SCH extends Healers
|
||||
case object AST extends Healers
|
||||
|
||||
case object MNK extends Mnks
|
||||
case object DRG extends Job {
|
||||
val leftSide: LeftSide = BodyDrgs
|
||||
val rightSide: RightSide = AccessoriesStr
|
||||
}
|
||||
case object NIN extends Job {
|
||||
val leftSide: LeftSide = BodyNins
|
||||
val rightSide: RightSide = AccessoriesDex
|
||||
}
|
||||
case object SAM extends Mnks
|
||||
|
||||
case object BRD extends Ranges
|
||||
case object MCH extends Ranges
|
||||
case object DNC extends Ranges
|
||||
|
||||
case object BLM extends Casters
|
||||
case object SMN extends Casters
|
||||
case object RDM extends Casters
|
||||
|
||||
lazy val jobs: Seq[Job] =
|
||||
Seq(PLD, WAR, DRK, GNB, WHM, SCH, AST, MNK, DRG, NIN, SAM, BRD, MCH, DNC, BLM, SMN, RDM)
|
||||
|
||||
def withName(job: String): Job.Job = jobs.find(_.toString == job.toUpperCase).getOrElse(AnyJob)
|
||||
}
|
||||
|
@ -6,20 +6,18 @@
|
||||
*
|
||||
* License: 3-clause BSD, see https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
package me.arcanis.ffxivbis.service
|
||||
package me.arcanis.ffxivbis.models
|
||||
|
||||
import com.typesafe.config.Config
|
||||
import com.typesafe.scalalogging.StrictLogging
|
||||
import me.arcanis.ffxivbis.models.{BiS, Loot, Piece, Player, PlayerId}
|
||||
import me.arcanis.ffxivbis.service.LootSelector
|
||||
|
||||
import scala.jdk.CollectionConverters._
|
||||
import scala.util.Random
|
||||
|
||||
case class Party(partyId: String, config: Config, players: Map[PlayerId, Player])
|
||||
case class Party(partyId: String, rules: Seq[String], players: Map[PlayerId, Player])
|
||||
extends StrictLogging {
|
||||
|
||||
private val rules =
|
||||
config.getStringList("me.arcanis.ffxivbis.settings.priority").asScala.toSeq
|
||||
require(players.keys.forall(_.partyId == partyId), "party id must be same")
|
||||
|
||||
def getPlayers: Seq[Player] = players.values.toSeq
|
||||
def player(playerId: PlayerId): Option[Player] = players.get(playerId)
|
||||
@ -38,8 +36,11 @@ case class Party(partyId: String, config: Config, players: Map[PlayerId, Player]
|
||||
}
|
||||
|
||||
object Party {
|
||||
private def getRules(config: Config): Seq[String] =
|
||||
config.getStringList("me.arcanis.ffxivbis.settings.priority").asScala.toSeq
|
||||
|
||||
def apply(partyId: Option[String], config: Config): Party =
|
||||
new Party(partyId.getOrElse(randomPartyId), config, Map.empty)
|
||||
new Party(partyId.getOrElse(randomPartyId), getRules(config), Map.empty)
|
||||
|
||||
def apply(partyId: String, config: Config,
|
||||
players: Map[Long, Player], bis: Seq[Loot], loot: Seq[Loot]): Party = {
|
||||
@ -51,7 +52,7 @@ object Party {
|
||||
.withBiS(bisByPlayer.get(playerId))
|
||||
.withLoot(lootByPlayer.get(playerId)))
|
||||
}
|
||||
Party(partyId, config, playersWithItems)
|
||||
Party(partyId, getRules(config), playersWithItems)
|
||||
}
|
||||
|
||||
def randomPartyId: String = Random.alphanumeric.take(20).mkString
|
@ -104,7 +104,7 @@ object Piece {
|
||||
case other => throw new Error(s"Unknown item type $other")
|
||||
}
|
||||
|
||||
def available: Seq[String] = Seq("weapon",
|
||||
lazy val available: Seq[String] = Seq("weapon",
|
||||
"head", "body", "hands", "waist", "legs", "feet",
|
||||
"ears", "neck", "wrist", "leftRing", "rightRing")
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ case class Player(partyId: String,
|
||||
loot: Seq[Piece],
|
||||
link: Option[String] = None,
|
||||
priority: Int = 0) {
|
||||
require(job != Job.AnyJob, "AnyJob is not allowed")
|
||||
require(job ne Job.AnyJob, "AnyJob is not allowed")
|
||||
|
||||
val playerId: PlayerId = PlayerId(partyId, job, nick)
|
||||
def withBiS(set: Option[BiS]): Player = set match {
|
||||
|
@ -23,13 +23,13 @@ case class PlayerId(partyId: String, job: Job.Job, nick: String) extends PlayerI
|
||||
object PlayerId {
|
||||
def apply(partyId: String, maybeNick: Option[String], maybeJob: Option[String]): Option[PlayerId] =
|
||||
(maybeNick, maybeJob) match {
|
||||
case (Some(nick), Some(job)) => Try(PlayerId(partyId, Job.fromString(job), nick)).toOption
|
||||
case (Some(nick), Some(job)) => Try(PlayerId(partyId, Job.withName(job), nick)).toOption
|
||||
case _ => None
|
||||
}
|
||||
|
||||
private val prettyPlayerIdRegex: Regex = "^(.*) \\(([A-Z]{3})\\)$".r
|
||||
def apply(partyId: String, player: String): Option[PlayerId] = player match {
|
||||
case s"${prettyPlayerIdRegex(nick, job)}" => Try(PlayerId(partyId, Job.fromString(job), nick)).toOption
|
||||
case s"${prettyPlayerIdRegex(nick, job)}" => Try(PlayerId(partyId, Job.withName(job), nick)).toOption
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ package me.arcanis.ffxivbis.service
|
||||
|
||||
import akka.actor.Actor
|
||||
import com.typesafe.scalalogging.StrictLogging
|
||||
import me.arcanis.ffxivbis.models.{Player, PlayerId}
|
||||
import me.arcanis.ffxivbis.models.{Party, Player, PlayerId}
|
||||
import me.arcanis.ffxivbis.storage.DatabaseProfile
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
@ -17,7 +17,7 @@ trait BiSProfile { this: DatabaseProfile =>
|
||||
import dbConfig.profile.api._
|
||||
|
||||
case class BiSRep(playerId: Long, created: Long, piece: String, isTome: Int, job: String) {
|
||||
def toLoot: Loot = Loot(playerId, Piece(piece, isTome == 1, Job.fromString(job)))
|
||||
def toLoot: Loot = Loot(playerId, Piece(piece, isTome == 1, Job.withName(job)))
|
||||
}
|
||||
object BiSRep {
|
||||
def fromPiece(playerId: Long, piece: Piece) =
|
||||
|
@ -18,7 +18,7 @@ trait LootProfile { this: DatabaseProfile =>
|
||||
|
||||
case class LootRep(lootId: Option[Long], playerId: Long, created: Long, piece: String,
|
||||
isTome: Int, job: String) {
|
||||
def toLoot: Loot = Loot(playerId, Piece(piece, isTome == 1, Job.fromString(job)))
|
||||
def toLoot: Loot = Loot(playerId, Piece(piece, isTome == 1, Job.withName(job)))
|
||||
}
|
||||
object LootRep {
|
||||
def fromPiece(playerId: Long, piece: Piece) =
|
||||
|
@ -19,7 +19,7 @@ trait PlayersProfile { this: DatabaseProfile =>
|
||||
case class PlayerRep(partyId: String, playerId: Option[Long], created: Long, nick: String,
|
||||
job: String, link: Option[String], priority: Int) {
|
||||
def toPlayer: Player =
|
||||
Player(partyId, Job.fromString(job), nick, BiS(Seq.empty), List.empty, link, priority)
|
||||
Player(partyId, Job.withName(job), nick, BiS(Seq.empty), List.empty, link, priority)
|
||||
}
|
||||
object PlayerRep {
|
||||
def fromPlayer(player: Player, id: Option[Long]): PlayerRep =
|
||||
|
Reference in New Issue
Block a user