mirror of
https://github.com/arcan1s/ffxivbis.git
synced 2025-04-24 17:27:17 +00:00
multi item support
This commit is contained in:
parent
25b05aa289
commit
2e16a8c1fa
@ -0,0 +1,2 @@
|
||||
drop index bis_piece_player_id_idx;
|
||||
create index bis_piece_type_player_id_idx on bis(player_id, piece, piece_type);
|
@ -0,0 +1,2 @@
|
||||
drop index bis_piece_player_id_idx;
|
||||
create index bis_piece_type_player_id_idx on bis(player_id, piece, piece_type);
|
@ -37,10 +37,13 @@ trait BiSHelper extends BisProviderHelper {
|
||||
}
|
||||
|
||||
def putBiS(playerId: PlayerId, link: String)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Unit] =
|
||||
downloadBiS(link, playerId.job).flatMap { bis =>
|
||||
Future.traverse(bis.pieces)(addPieceBiS(playerId, _))
|
||||
}.map(_ => ())
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Unit] = {
|
||||
(storage ? DatabaseBiSHandler.RemovePiecesFromBiS(playerId)).flatMap { _ =>
|
||||
downloadBiS(link, playerId.job).flatMap { bis =>
|
||||
Future.traverse(bis.pieces)(addPieceBiS(playerId, _))
|
||||
}.map(_ => ())
|
||||
}
|
||||
}
|
||||
|
||||
def removePieceBiS(playerId: PlayerId, piece: Piece)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] =
|
||||
|
@ -21,13 +21,15 @@ case class PlayerResponse(
|
||||
@Schema(description = "player loot priority", `type` = "number") priority: Option[Int]) {
|
||||
def toPlayer: Player =
|
||||
Player(-1, partyId, Job.withName(job), nick,
|
||||
BiS(bis.getOrElse(Seq.empty).map(_.toPiece)), loot.getOrElse(Seq.empty).map(_.toLoot),
|
||||
BiS(bis.getOrElse(Seq.empty).map(_.toPiece)),
|
||||
loot.getOrElse(Seq.empty).map(_.toLoot),
|
||||
link, priority.getOrElse(0))
|
||||
}
|
||||
|
||||
object PlayerResponse {
|
||||
def fromPlayer(player: Player): PlayerResponse =
|
||||
PlayerResponse(player.partyId, player.job.toString, player.nick,
|
||||
Some(player.bis.pieces.map(PieceResponse.fromPiece)), Some(player.loot.map(LootResponse.fromLoot)),
|
||||
Some(player.bis.pieces.map(PieceResponse.fromPiece)),
|
||||
Some(player.loot.map(LootResponse.fromLoot)),
|
||||
player.link, Some(player.priority))
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ object BiSView {
|
||||
input(name:="add", id:="add", `type`:="submit", value:="add")
|
||||
),
|
||||
|
||||
form(action:="/bis", method:="post")(
|
||||
form(action:=s"/party/$partyId/bis", method:="post")(
|
||||
select(name:="player", id:="player", title:="player")
|
||||
(for (player <- party) yield option(player.playerId.toString)),
|
||||
input(name:="link", id:="link", placeholder:="player bis link", title:="link", `type`:="text"),
|
||||
|
@ -47,8 +47,8 @@ class PlayerView(override val storage: ActorRef, override val ariyala: ActorRef)
|
||||
post {
|
||||
formFields("nick".as[String], "job".as[String], "priority".as[Int].?, "link".as[String].?, "action".as[String]) {
|
||||
(nick, job, maybePriority, maybeLink, action) =>
|
||||
onComplete(modifyPartyCall(partyId, nick, job, maybePriority, maybeLink, action)) {
|
||||
case _ => redirect(s"/party/$partyId/players", StatusCodes.Found)
|
||||
onComplete(modifyPartyCall(partyId, nick, job, maybePriority, maybeLink, action)) { _ =>
|
||||
redirect(s"/party/$partyId/players", StatusCodes.Found)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,7 +62,7 @@ class PlayerView(override val storage: ActorRef, override val ariyala: ActorRef)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Unit] = {
|
||||
def maybePlayerId = PlayerId(partyId, Some(nick), Some(job))
|
||||
def player(playerId: PlayerId) =
|
||||
Player(-1, partyId, playerId.job, playerId.nick, BiS(), Seq.empty, maybeLink, maybePriority.getOrElse(0))
|
||||
Player(-1, partyId, playerId.job, playerId.nick, BiS.empty, Seq.empty, maybeLink, maybePriority.getOrElse(0))
|
||||
|
||||
(action, maybePlayerId) match {
|
||||
case ("add", Some(playerId)) => addPlayer(player(playerId)).map(_ => ())
|
||||
|
@ -8,21 +8,7 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.models
|
||||
|
||||
case class BiS(weapon: Option[Piece],
|
||||
head: Option[Piece],
|
||||
body: Option[Piece],
|
||||
hands: Option[Piece],
|
||||
waist: Option[Piece],
|
||||
legs: Option[Piece],
|
||||
feet: Option[Piece],
|
||||
ears: Option[Piece],
|
||||
neck: Option[Piece],
|
||||
wrist: Option[Piece],
|
||||
leftRing: Option[Piece],
|
||||
rightRing: Option[Piece]) {
|
||||
|
||||
val pieces: Seq[Piece] =
|
||||
Seq(weapon, head, body, hands, waist, legs, feet, ears, neck, wrist, leftRing, rightRing).flatten
|
||||
case class BiS(pieces: Seq[Piece]) {
|
||||
|
||||
def hasPiece(piece: Piece): Boolean = piece match {
|
||||
case upgrade: PieceUpgrade => upgrades.contains(upgrade)
|
||||
@ -31,50 +17,27 @@ case class BiS(weapon: Option[Piece],
|
||||
|
||||
def upgrades: Map[PieceUpgrade, Int] =
|
||||
pieces.groupBy(_.upgrade).foldLeft(Map.empty[PieceUpgrade, Int]) {
|
||||
case (acc, (Some(k), v)) => acc + (k -> v.length)
|
||||
case (acc, (Some(k), v)) => acc + (k -> v.size)
|
||||
case (acc, _) => acc
|
||||
} withDefaultValue 0
|
||||
|
||||
def withPiece(piece: Piece): BiS = copyWithPiece(piece.piece, Some(piece))
|
||||
def withoutPiece(piece: Piece): BiS = copyWithPiece(piece.piece, None)
|
||||
def withPiece(piece: Piece): BiS = copy(pieces :+ piece)
|
||||
def withoutPiece(piece: Piece): BiS = copy(pieces.filterNot(_.strictEqual(piece)))
|
||||
|
||||
private def copyWithPiece(name: String, piece: Option[Piece]): BiS = {
|
||||
val params = Map(
|
||||
"weapon" -> weapon,
|
||||
"head" -> head,
|
||||
"body" -> body,
|
||||
"hands" -> hands,
|
||||
"waist" -> waist,
|
||||
"legs" -> legs,
|
||||
"feet" -> feet,
|
||||
"ears" -> ears,
|
||||
"neck" -> neck,
|
||||
"wrist" -> wrist,
|
||||
"left ring" -> leftRing,
|
||||
"right ring" -> rightRing
|
||||
) + (name -> piece)
|
||||
BiS(params)
|
||||
override def equals(obj: Any): Boolean = {
|
||||
def comparePieces(left: Seq[Piece], right: Seq[Piece]): Boolean =
|
||||
left.groupBy(identity).view.mapValues(_.size).forall {
|
||||
case (key, count) => right.count(_.strictEqual(key)) == count
|
||||
}
|
||||
|
||||
obj match {
|
||||
case left: BiS => comparePieces(left.pieces, pieces)
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object BiS {
|
||||
def apply(data: Map[String, Option[Piece]]): BiS =
|
||||
BiS(
|
||||
data.get("weapon").flatten,
|
||||
data.get("head").flatten,
|
||||
data.get("body").flatten,
|
||||
data.get("hands").flatten,
|
||||
data.get("waist").flatten,
|
||||
data.get("legs").flatten,
|
||||
data.get("feet").flatten,
|
||||
data.get("ears").flatten,
|
||||
data.get("neck").flatten,
|
||||
data.get("wrist").flatten,
|
||||
data.get("left ring").flatten,
|
||||
data.get("right ring").flatten)
|
||||
|
||||
def apply(): BiS = BiS(Seq.empty)
|
||||
|
||||
def apply(pieces: Seq[Piece]): BiS =
|
||||
BiS(pieces.map(piece => piece.piece -> Some(piece)).toMap)
|
||||
def empty: BiS = BiS(Seq.empty)
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
package me.arcanis.ffxivbis.models
|
||||
|
||||
object Job {
|
||||
|
||||
sealed trait RightSide
|
||||
object AccessoriesDex extends RightSide
|
||||
object AccessoriesInt extends RightSide
|
||||
@ -26,6 +27,7 @@ object Job {
|
||||
object BodyRanges extends LeftSide
|
||||
|
||||
sealed trait Job {
|
||||
|
||||
def leftSide: LeftSide
|
||||
def rightSide: RightSide
|
||||
|
||||
|
@ -11,5 +11,6 @@ package me.arcanis.ffxivbis.models
|
||||
import java.time.Instant
|
||||
|
||||
case class Loot(playerId: Long, piece: Piece, timestamp: Instant, isFreeLoot: Boolean) {
|
||||
|
||||
def isFreeLootToString: String = if (isFreeLoot) "yes" else "no"
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ case class Party(partyDescription: PartyDescription, rules: Seq[String], players
|
||||
}
|
||||
|
||||
object Party {
|
||||
|
||||
def apply(party: PartyDescription, config: Config,
|
||||
players: Map[Long, Player], bis: Seq[Loot], loot: Seq[Loot]): Party = {
|
||||
val bisByPlayer = bis.groupBy(_.playerId).view.mapValues(piece => BiS(piece.map(_.piece)))
|
||||
|
@ -9,9 +9,11 @@
|
||||
package me.arcanis.ffxivbis.models
|
||||
|
||||
case class PartyDescription(partyId: String, partyAlias: Option[String]) {
|
||||
|
||||
def alias: String = partyAlias.getOrElse(partyId)
|
||||
}
|
||||
|
||||
object PartyDescription {
|
||||
|
||||
def empty(partyId: String): PartyDescription = PartyDescription(partyId, None)
|
||||
}
|
@ -8,7 +8,8 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.models
|
||||
|
||||
sealed trait Piece {
|
||||
sealed trait Piece extends Equals {
|
||||
|
||||
def pieceType: PieceType.PieceType
|
||||
def job: Job.Job
|
||||
def piece: String
|
||||
@ -22,6 +23,9 @@ sealed trait Piece {
|
||||
case _: PieceBody => Some(BodyUpgrade)
|
||||
case _: PieceWeapon => Some(WeaponUpgrade)
|
||||
}
|
||||
|
||||
// used for ring comparison
|
||||
def strictEqual(obj: Any): Boolean = equals(obj)
|
||||
}
|
||||
|
||||
trait PieceAccessory extends Piece
|
||||
@ -78,10 +82,16 @@ case class Wrist(override val pieceType: PieceType.PieceType, override val job:
|
||||
case class Ring(override val pieceType: PieceType.PieceType, override val job: Job.Job, override val piece: String = "ring")
|
||||
extends PieceAccessory {
|
||||
def withJob(other: Job.Job): Piece = copy(job = other)
|
||||
|
||||
override def equals(obj: Any): Boolean = obj match {
|
||||
case Ring(thatPieceType, thatJob, _) => (thatPieceType == pieceType) && (thatJob == job)
|
||||
case _ => false
|
||||
}
|
||||
|
||||
override def strictEqual(obj: Any): Boolean = obj match {
|
||||
case ring: Ring => equals(obj) && (ring.piece == this.piece)
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
|
||||
case object AccessoryUpgrade extends PieceUpgrade {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package me.arcanis.ffxivbis.models
|
||||
|
||||
object PieceType {
|
||||
|
||||
sealed trait PieceType
|
||||
|
||||
case object Crafted extends PieceType
|
||||
|
@ -12,6 +12,7 @@ import scala.util.Try
|
||||
import scala.util.matching.Regex
|
||||
|
||||
trait PlayerIdBase {
|
||||
|
||||
def job: Job.Job
|
||||
def nick: String
|
||||
|
||||
@ -21,6 +22,7 @@ trait PlayerIdBase {
|
||||
case class PlayerId(partyId: String, job: Job.Job, nick: String) extends PlayerIdBase
|
||||
|
||||
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.withName(job), nick)).toOption
|
||||
|
@ -38,6 +38,7 @@ case class PlayerIdWithCounters(partyId: String,
|
||||
}
|
||||
|
||||
object PlayerIdWithCounters {
|
||||
|
||||
private case class PlayerCountersComparator(values: Int*) {
|
||||
def >(that: PlayerCountersComparator): Boolean = {
|
||||
@scala.annotation.tailrec
|
||||
|
@ -29,6 +29,10 @@ trait DatabaseBiSHandler { this: Database =>
|
||||
case RemovePieceFromBiS(playerId, piece) =>
|
||||
val client = sender()
|
||||
profile.deletePieceBiS(playerId, piece).pipeTo(client)
|
||||
|
||||
case RemovePiecesFromBiS(playerId) =>
|
||||
val client = sender()
|
||||
profile.deletePiecesBiS(playerId).pipeTo(client)
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,4 +44,7 @@ object DatabaseBiSHandler {
|
||||
case class RemovePieceFromBiS(playerId: PlayerId, piece: Piece) extends Database.DatabaseRequest {
|
||||
override def partyId: String = playerId.partyId
|
||||
}
|
||||
case class RemovePiecesFromBiS(playerId: PlayerId) extends Database.DatabaseRequest {
|
||||
override def partyId: String = playerId.partyId
|
||||
}
|
||||
}
|
||||
|
@ -46,14 +46,21 @@ trait BiSProfile { this: DatabaseProfile =>
|
||||
|
||||
def deletePieceBiSById(piece: Piece)(playerId: Long): Future[Int] =
|
||||
db.run(pieceBiS(BiSRep.fromPiece(playerId, piece)).delete)
|
||||
def deletePiecesBiSById(playerId: Long): Future[Int] =
|
||||
db.run(piecesBiS(Seq(playerId)).delete)
|
||||
def getPiecesBiSById(playerId: Long): Future[Seq[Loot]] = getPiecesBiSById(Seq(playerId))
|
||||
def getPiecesBiSById(playerIds: Seq[Long]): Future[Seq[Loot]] =
|
||||
db.run(piecesBiS(playerIds).result).map(_.map(_.toLoot))
|
||||
def insertPieceBiSById(piece: Piece)(playerId: Long): Future[Int] =
|
||||
db.run(bisTable.insertOrUpdate(BiSRep.fromPiece(playerId, piece)))
|
||||
getPiecesBiSById(playerId).flatMap {
|
||||
case pieces if pieces.exists(loot => loot.piece.strictEqual(piece)) => Future.successful(0)
|
||||
case _ => db.run(bisTable.insertOrUpdate(BiSRep.fromPiece(playerId, piece)))
|
||||
}
|
||||
|
||||
private def pieceBiS(piece: BiSRep) =
|
||||
piecesBiS(Seq(piece.playerId)).filter(_.piece === piece.piece)
|
||||
piecesBiS(Seq(piece.playerId)).filter { stored =>
|
||||
(stored.piece === piece.piece) && (stored.pieceType === piece.pieceType)
|
||||
}
|
||||
private def piecesBiS(playerIds: Seq[Long]) =
|
||||
bisTable.filter(_.playerId.inSet(playerIds.toSet))
|
||||
}
|
||||
|
@ -36,6 +36,8 @@ class DatabaseProfile(context: ExecutionContext, config: Config)
|
||||
// generic bis api
|
||||
def deletePieceBiS(playerId: PlayerId, piece: Piece): Future[Int] =
|
||||
byPlayerId(playerId, deletePieceBiSById(piece))
|
||||
def deletePiecesBiS(playerId: PlayerId): Future[Int] =
|
||||
byPlayerId(playerId, deletePiecesBiSById)
|
||||
def getPiecesBiS(playerId: PlayerId): Future[Seq[Loot]] =
|
||||
byPlayerId(playerId, getPiecesBiSById)
|
||||
def getPiecesBiS(partyId: String): Future[Seq[Loot]] =
|
||||
@ -57,7 +59,7 @@ class DatabaseProfile(context: ExecutionContext, config: Config)
|
||||
byPlayerId(playerId, insertPieceById(loot))
|
||||
|
||||
private def byPartyId[T](partyId: String, callback: Seq[Long] => Future[T]): Future[T] =
|
||||
getPlayers(partyId).map(callback).flatten
|
||||
getPlayers(partyId).flatMap(callback)
|
||||
private def byPlayerId[T](playerId: PlayerId, callback: Long => Future[T]): Future[T] =
|
||||
getPlayer(playerId).flatMap {
|
||||
case Some(id) => callback(id)
|
||||
|
@ -19,7 +19,7 @@ trait PlayersProfile { this: DatabaseProfile =>
|
||||
nick: String, job: String, link: Option[String], priority: Int) {
|
||||
def toPlayer: Player =
|
||||
Player(playerId.getOrElse(-1), partyId, Job.withName(job), nick,
|
||||
BiS(Seq.empty), List.empty, link, priority)
|
||||
BiS.empty, Seq.empty, link, priority)
|
||||
}
|
||||
object PlayerRep {
|
||||
def fromPlayer(player: Player, id: Option[Long]): PlayerRep =
|
||||
|
@ -26,6 +26,7 @@ object Fixtures {
|
||||
|
||||
lazy val lootWeapon: Piece = Weapon(pieceType = PieceType.Tome, Job.AnyJob)
|
||||
lazy val lootBody: Piece = Body(pieceType = PieceType.Savage, Job.AnyJob)
|
||||
lazy val lootBodyCrafted: Piece = Body(pieceType = PieceType.Crafted, Job.AnyJob)
|
||||
lazy val lootHands: Piece = Hands(pieceType = PieceType.Tome, Job.AnyJob)
|
||||
lazy val lootWaist: Piece = Waist(pieceType = PieceType.Tome, Job.AnyJob)
|
||||
lazy val lootLegs: Piece = Legs(pieceType = PieceType.Savage, Job.AnyJob)
|
||||
@ -40,7 +41,7 @@ object Fixtures {
|
||||
lazy val partyId2: String = Party.randomPartyId
|
||||
|
||||
lazy val playerEmpty: Player =
|
||||
Player(1, partyId, Job.DNC, "Siuan Sanche", BiS(), Seq.empty, Some(link))
|
||||
Player(1, partyId, Job.DNC, "Siuan Sanche", BiS.empty, Seq.empty, Some(link))
|
||||
lazy val playerWithBiS: Player = playerEmpty.copy(bis = bis)
|
||||
|
||||
lazy val userPassword: String = "password"
|
||||
|
@ -10,10 +10,11 @@ import akka.testkit.TestKit
|
||||
import com.typesafe.config.Config
|
||||
import me.arcanis.ffxivbis.{Fixtures, Settings}
|
||||
import me.arcanis.ffxivbis.http.api.v1.json._
|
||||
import me.arcanis.ffxivbis.models.BiS
|
||||
import me.arcanis.ffxivbis.models.{BiS, Body, Job, PieceType}
|
||||
import me.arcanis.ffxivbis.service.bis.BisProvider
|
||||
import me.arcanis.ffxivbis.service.{PartyService, impl}
|
||||
import me.arcanis.ffxivbis.storage.Migration
|
||||
import me.arcanis.ffxivbis.utils.Compare
|
||||
import org.scalatest.{Matchers, WordSpec}
|
||||
|
||||
import scala.concurrent.Await
|
||||
@ -48,6 +49,15 @@ class BiSEndpointTest extends WordSpec
|
||||
Settings.clearDatabase(system.settings.config)
|
||||
}
|
||||
|
||||
private def compareBiSResponse(actual: PlayerResponse, expected: PlayerResponse): Unit = {
|
||||
actual.partyId shouldEqual expected.partyId
|
||||
actual.nick shouldEqual expected.nick
|
||||
actual.job shouldEqual expected.job
|
||||
Compare.seqEquals(actual.bis.get, expected.bis.get) shouldEqual true
|
||||
actual.link shouldEqual expected.link
|
||||
actual.priority shouldEqual expected.priority
|
||||
}
|
||||
|
||||
"api v1 bis endpoint" must {
|
||||
|
||||
"create best in slot set from ariyala" in {
|
||||
@ -61,11 +71,13 @@ class BiSEndpointTest extends WordSpec
|
||||
|
||||
"return best in slot set" in {
|
||||
val uri = endpoint.withQuery(Uri.Query(Map("nick" -> playerId.nick, "job" -> playerId.job)))
|
||||
val response = Seq(PlayerResponse.fromPlayer(Fixtures.playerEmpty.withBiS(Some(Fixtures.bis))))
|
||||
val response = PlayerResponse.fromPlayer(Fixtures.playerEmpty.withBiS(Some(Fixtures.bis)))
|
||||
|
||||
Get(uri).withHeaders(auth) ~> route ~> check {
|
||||
status shouldEqual StatusCodes.OK
|
||||
responseAs[Seq[PlayerResponse]] shouldEqual response
|
||||
val actual = responseAs[Seq[PlayerResponse]]
|
||||
actual.length shouldEqual 1
|
||||
actual.foreach(compareBiSResponse(_, response))
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,11 +92,13 @@ class BiSEndpointTest extends WordSpec
|
||||
|
||||
val uri = endpoint.withQuery(Uri.Query(Map("nick" -> playerId.nick, "job" -> playerId.job)))
|
||||
val bis = BiS(Fixtures.bis.pieces.filterNot(_ == Fixtures.lootBody))
|
||||
val response = Seq(PlayerResponse.fromPlayer(Fixtures.playerEmpty.withBiS(Some(bis))))
|
||||
val response = PlayerResponse.fromPlayer(Fixtures.playerEmpty.withBiS(Some(bis)))
|
||||
|
||||
Get(uri).withHeaders(auth) ~> route ~> check {
|
||||
status shouldEqual StatusCodes.OK
|
||||
responseAs[Seq[PlayerResponse]] shouldEqual response
|
||||
val actual = responseAs[Seq[PlayerResponse]]
|
||||
actual.length shouldEqual 1
|
||||
actual.foreach(compareBiSResponse(_, response))
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,11 +112,102 @@ class BiSEndpointTest extends WordSpec
|
||||
}
|
||||
|
||||
val uri = endpoint.withQuery(Uri.Query(Map("nick" -> playerId.nick, "job" -> playerId.job)))
|
||||
val response = Seq(PlayerResponse.fromPlayer(Fixtures.playerEmpty.withBiS(Some(Fixtures.bis))))
|
||||
val response = PlayerResponse.fromPlayer(Fixtures.playerEmpty.withBiS(Some(Fixtures.bis)))
|
||||
|
||||
Get(uri).withHeaders(auth) ~> route ~> check {
|
||||
status shouldEqual StatusCodes.OK
|
||||
responseAs[Seq[PlayerResponse]] shouldEqual response
|
||||
val actual = responseAs[Seq[PlayerResponse]]
|
||||
actual.length shouldEqual 1
|
||||
actual.foreach(compareBiSResponse(_, response))
|
||||
}
|
||||
}
|
||||
|
||||
"do not allow to add same item to best in slot set" in {
|
||||
val piece = PieceResponse.fromPiece(Fixtures.lootBody.withJob(Job.DNC))
|
||||
val entity = PieceActionResponse(ApiAction.add, piece, playerId, None)
|
||||
|
||||
Post(endpoint, entity).withHeaders(auth) ~> route ~> check {
|
||||
status shouldEqual StatusCodes.Accepted
|
||||
responseAs[String] shouldEqual ""
|
||||
}
|
||||
|
||||
val uri = endpoint.withQuery(Uri.Query(Map("nick" -> playerId.nick, "job" -> playerId.job)))
|
||||
val response = PlayerResponse.fromPlayer(Fixtures.playerEmpty.withBiS(Some(Fixtures.bis)))
|
||||
|
||||
Get(uri).withHeaders(auth) ~> route ~> check {
|
||||
status shouldEqual StatusCodes.OK
|
||||
val actual = responseAs[Seq[PlayerResponse]]
|
||||
actual.length shouldEqual 1
|
||||
actual.foreach(compareBiSResponse(_, response))
|
||||
}
|
||||
}
|
||||
|
||||
"allow to add item with another type to best in slot set" in {
|
||||
val piece = PieceResponse.fromPiece(Fixtures.lootBodyCrafted.withJob(Job.DNC))
|
||||
val entity = PieceActionResponse(ApiAction.add, piece, playerId, None)
|
||||
|
||||
Post(endpoint, entity).withHeaders(auth) ~> route ~> check {
|
||||
status shouldEqual StatusCodes.Accepted
|
||||
responseAs[String] shouldEqual ""
|
||||
}
|
||||
|
||||
val uri = endpoint.withQuery(Uri.Query(Map("nick" -> playerId.nick, "job" -> playerId.job)))
|
||||
val bis = Fixtures.bis.withPiece(piece.toPiece)
|
||||
val response = PlayerResponse.fromPlayer(Fixtures.playerEmpty.withBiS(Some(bis)))
|
||||
|
||||
Get(uri).withHeaders(auth) ~> route ~> check {
|
||||
status shouldEqual StatusCodes.OK
|
||||
val actual = responseAs[Seq[PlayerResponse]]
|
||||
actual.length shouldEqual 1
|
||||
actual.foreach(compareBiSResponse(_, response))
|
||||
}
|
||||
}
|
||||
|
||||
"remove only specific item from best in slot set" in {
|
||||
val piece = PieceResponse.fromPiece(Fixtures.lootBodyCrafted.withJob(Job.DNC))
|
||||
val entity = PieceActionResponse(ApiAction.remove, piece, playerId, None)
|
||||
|
||||
Post(endpoint, entity).withHeaders(auth) ~> route ~> check {
|
||||
status shouldEqual StatusCodes.Accepted
|
||||
responseAs[String] shouldEqual ""
|
||||
}
|
||||
|
||||
val uri = endpoint.withQuery(Uri.Query(Map("nick" -> playerId.nick, "job" -> playerId.job)))
|
||||
val response = PlayerResponse.fromPlayer(Fixtures.playerEmpty.withBiS(Some(Fixtures.bis)))
|
||||
|
||||
Get(uri).withHeaders(auth) ~> route ~> check {
|
||||
status shouldEqual StatusCodes.OK
|
||||
val actual = responseAs[Seq[PlayerResponse]]
|
||||
actual.length shouldEqual 1
|
||||
actual.foreach(compareBiSResponse(_, response))
|
||||
}
|
||||
}
|
||||
|
||||
"totaly replace player bis" in {
|
||||
// add random item first
|
||||
val piece = PieceResponse.fromPiece(Fixtures.lootBodyCrafted.withJob(Job.DNC))
|
||||
val entity = PieceActionResponse(ApiAction.add, piece, playerId, None)
|
||||
|
||||
Post(endpoint, entity).withHeaders(auth) ~> route ~> check {
|
||||
status shouldEqual StatusCodes.Accepted
|
||||
responseAs[String] shouldEqual ""
|
||||
}
|
||||
|
||||
val bisEntity = PlayerBiSLinkResponse(Fixtures.link, playerId)
|
||||
|
||||
Put(endpoint, bisEntity).withHeaders(auth) ~> route ~> check {
|
||||
status shouldEqual StatusCodes.Created
|
||||
responseAs[String] shouldEqual ""
|
||||
}
|
||||
|
||||
val uri = endpoint.withQuery(Uri.Query(Map("nick" -> playerId.nick, "job" -> playerId.job)))
|
||||
val response = PlayerResponse.fromPlayer(Fixtures.playerEmpty.withBiS(Some(Fixtures.bis)))
|
||||
|
||||
Get(uri).withHeaders(auth) ~> route ~> check {
|
||||
status shouldEqual StatusCodes.OK
|
||||
val actual = responseAs[Seq[PlayerResponse]]
|
||||
actual.length shouldEqual 1
|
||||
actual.foreach(compareBiSResponse(_, response))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,18 +29,14 @@ class BiSTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
val bis = BiS(Seq(Fixtures.lootLegs))
|
||||
val newBis = bis.withPiece(Fixtures.lootHands)
|
||||
|
||||
newBis.legs shouldEqual Some(Fixtures.lootLegs)
|
||||
newBis.hands shouldEqual Some(Fixtures.lootHands)
|
||||
newBis.pieces.length shouldEqual 2
|
||||
newBis shouldEqual BiS(Seq(Fixtures.lootLegs, Fixtures.lootHands))
|
||||
}
|
||||
|
||||
"create copy without piece" in {
|
||||
val bis = BiS(Seq(Fixtures.lootHands, Fixtures.lootLegs))
|
||||
val newBis = bis.withoutPiece(Fixtures.lootHands)
|
||||
|
||||
newBis.legs shouldEqual Some(Fixtures.lootLegs)
|
||||
newBis.hands shouldEqual None
|
||||
newBis.pieces.length shouldEqual 1
|
||||
newBis shouldEqual BiS(Seq(Fixtures.lootLegs))
|
||||
}
|
||||
|
||||
"ignore upgrade on modification" in {
|
||||
|
@ -72,7 +72,7 @@ class DatabaseBiSHandlerTest
|
||||
|
||||
database ! impl.DatabaseBiSHandler.GetBiS(Fixtures.playerEmpty.partyId, None)
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyBiSCompare(party, Seq(newPiece)) => ()
|
||||
case party: Seq[_] if partyBiSCompare(party, Seq(Fixtures.lootHands, newPiece)) => ()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,8 @@ class LootSelectorTest extends TestKit(ActorSystem("lootselector"))
|
||||
import me.arcanis.ffxivbis.utils.Converters._
|
||||
|
||||
private var default: Party = Party(PartyDescription.empty(Fixtures.partyId), Settings.config(Map.empty), Map.empty, Seq.empty, Seq.empty)
|
||||
private var dnc: Player = Player(-1, Fixtures.partyId, Job.DNC, "a nick", BiS(), Seq.empty, Some(Fixtures.link))
|
||||
private var drg: Player = Player(-1, Fixtures.partyId, Job.DRG, "another nick", BiS(), Seq.empty, Some(Fixtures.link2))
|
||||
private var dnc: Player = Player(-1, Fixtures.partyId, Job.DNC, "a nick", BiS.empty, Seq.empty, Some(Fixtures.link))
|
||||
private var drg: Player = Player(-1, Fixtures.partyId, Job.DRG, "another nick", BiS.empty, Seq.empty, Some(Fixtures.link2))
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
|
||||
override def beforeAll(): Unit = {
|
||||
@ -51,7 +51,7 @@ class LootSelectorTest extends TestKit(ActorSystem("lootselector"))
|
||||
"suggest upgrade" in {
|
||||
val party = default.withPlayer(
|
||||
dnc.withBiS(
|
||||
Some(dnc.bis.copy(weapon = Some(Weapon(pieceType = PieceType.Tome, Job.DNC))))
|
||||
Some(dnc.bis.withPiece(Weapon(pieceType = PieceType.Tome, Job.DNC)))
|
||||
)
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user