mirror of
https://github.com/arcan1s/ffxivbis.git
synced 2025-04-28 10:57:18 +00:00
another test for bis part
This commit is contained in:
parent
0ed9e92441
commit
99ed2705a2
@ -24,7 +24,7 @@ trait PlayerHelper extends BisProviderHelper {
|
|||||||
def addPlayer(player: Player)
|
def addPlayer(player: Player)
|
||||||
(implicit executionContext: ExecutionContext, timeout: Timeout, scheduler: Scheduler): Future[Unit] =
|
(implicit executionContext: ExecutionContext, timeout: Timeout, scheduler: Scheduler): Future[Unit] =
|
||||||
storage.ask(ref => AddPlayer(player, ref)).map { res =>
|
storage.ask(ref => AddPlayer(player, ref)).map { res =>
|
||||||
player.link match {
|
player.link.map(_.trim).filter(_.nonEmpty) match {
|
||||||
case Some(link) =>
|
case Some(link) =>
|
||||||
downloadBiS(link, player.job).map { bis =>
|
downloadBiS(link, player.job).map { bis =>
|
||||||
bis.pieces.map(piece => storage.ask(AddPieceToBis(player.playerId, piece, _)))
|
bis.pieces.map(piece => storage.ask(AddPieceToBis(player.playerId, piece, _)))
|
||||||
|
@ -74,7 +74,7 @@ class BiSView(override val storage: ActorRef[Message],
|
|||||||
}
|
}
|
||||||
|
|
||||||
PlayerId(partyId, player) match {
|
PlayerId(partyId, player) match {
|
||||||
case Some(playerId) => (maybePiece, maybePieceType, action, maybeLink) match {
|
case Some(playerId) => (maybePiece, maybePieceType, action, maybeLink.map(_.trim).filter(_.nonEmpty)) match {
|
||||||
case (Some(piece), Some(pieceType), "add", _) =>
|
case (Some(piece), Some(pieceType), "add", _) =>
|
||||||
bisAction(playerId, piece, pieceType)(addPieceBiS(playerId, _))
|
bisAction(playerId, piece, pieceType)(addPieceBiS(playerId, _))
|
||||||
case (Some(piece), Some(pieceType), "remove", _) =>
|
case (Some(piece), Some(pieceType), "remove", _) =>
|
||||||
|
@ -89,6 +89,8 @@ object LootSuggestView {
|
|||||||
body(
|
body(
|
||||||
h2("Suggest loot"),
|
h2("Suggest loot"),
|
||||||
|
|
||||||
|
for (part <- piece) yield p(s"Piece ${part.piece} (${part.pieceType})"),
|
||||||
|
|
||||||
ErrorView.template(error),
|
ErrorView.template(error),
|
||||||
SearchLineView.template,
|
SearchLineView.template,
|
||||||
|
|
||||||
|
@ -5,4 +5,7 @@ import me.arcanis.ffxivbis.models.{BiS, Job}
|
|||||||
|
|
||||||
sealed trait BiSProviderMessage
|
sealed trait BiSProviderMessage
|
||||||
|
|
||||||
case class DownloadBiS(link: String, job: Job.Job, replyTo: ActorRef[BiS]) extends BiSProviderMessage
|
case class DownloadBiS(link: String, job: Job.Job, replyTo: ActorRef[BiS]) extends BiSProviderMessage {
|
||||||
|
|
||||||
|
require(link.nonEmpty && link.trim == link, "Link must be not empty and contain no spaces")
|
||||||
|
}
|
||||||
|
@ -14,10 +14,10 @@ import spray.json.{JsNumber, JsObject, JsString, deserializationError}
|
|||||||
|
|
||||||
import scala.concurrent.{ExecutionContext, Future}
|
import scala.concurrent.{ExecutionContext, Future}
|
||||||
|
|
||||||
object Ariyala {
|
object Ariyala extends IdParser {
|
||||||
|
|
||||||
def idParser(job: Job.Job, js: JsObject)
|
override def parse(job: Job.Job, js: JsObject)
|
||||||
(implicit executionContext: ExecutionContext): Future[Map[String, Long]] =
|
(implicit executionContext: ExecutionContext): Future[Map[String, Long]] =
|
||||||
Future {
|
Future {
|
||||||
val apiJob = js.fields.get("content") match {
|
val apiJob = js.fields.get("content") match {
|
||||||
case Some(JsString(value)) => value
|
case Some(JsString(value)) => value
|
||||||
@ -37,7 +37,7 @@ object Ariyala {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def uri(root: Uri, id: String): Uri =
|
override def uri(root: Uri, id: String): Uri =
|
||||||
root
|
root
|
||||||
.withPath(Uri.Path / "store.app")
|
.withPath(Uri.Path / "store.app")
|
||||||
.withQuery(Uri.Query(Map("identifier" -> id)))
|
.withQuery(Uri.Query(Map("identifier" -> id)))
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
package me.arcanis.ffxivbis.service.bis
|
package me.arcanis.ffxivbis.service.bis
|
||||||
|
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
|
|
||||||
import akka.actor.ClassicActorSystemProvider
|
import akka.actor.ClassicActorSystemProvider
|
||||||
import akka.actor.typed.{Behavior, PostStop, Signal}
|
import akka.actor.typed.{Behavior, PostStop, Signal}
|
||||||
import akka.actor.typed.scaladsl.{AbstractBehavior, ActorContext, Behaviors}
|
import akka.actor.typed.scaladsl.{AbstractBehavior, ActorContext, Behaviors}
|
||||||
@ -20,6 +19,7 @@ import me.arcanis.ffxivbis.models.{BiS, Job, Piece, PieceType}
|
|||||||
import spray.json._
|
import spray.json._
|
||||||
|
|
||||||
import scala.concurrent.{ExecutionContext, Future}
|
import scala.concurrent.{ExecutionContext, Future}
|
||||||
|
import scala.util.{Failure, Success}
|
||||||
|
|
||||||
class BisProvider(context: ActorContext[BiSProviderMessage])
|
class BisProvider(context: ActorContext[BiSProviderMessage])
|
||||||
extends AbstractBehavior[BiSProviderMessage](context) with XivApi with StrictLogging {
|
extends AbstractBehavior[BiSProviderMessage](context) with XivApi with StrictLogging {
|
||||||
@ -29,7 +29,11 @@ class BisProvider(context: ActorContext[BiSProviderMessage])
|
|||||||
override def onMessage(msg: BiSProviderMessage): Behavior[BiSProviderMessage] =
|
override def onMessage(msg: BiSProviderMessage): Behavior[BiSProviderMessage] =
|
||||||
msg match {
|
msg match {
|
||||||
case DownloadBiS(link, job, client) =>
|
case DownloadBiS(link, job, client) =>
|
||||||
get(link, job).map(BiS(_)).foreach(client ! _)
|
get(link, job).onComplete {
|
||||||
|
case Success(items) => client ! BiS(items)
|
||||||
|
case Failure(exception) =>
|
||||||
|
logger.error("received exception while getting items", exception)
|
||||||
|
}
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,14 +47,9 @@ class BisProvider(context: ActorContext[BiSProviderMessage])
|
|||||||
val url = Uri(link)
|
val url = Uri(link)
|
||||||
val id = Paths.get(link).normalize.getFileName.toString
|
val id = Paths.get(link).normalize.getFileName.toString
|
||||||
|
|
||||||
val (idParser, uri) =
|
val parser = if (url.authority.host.address().contains("etro")) Etro else Ariyala
|
||||||
if (url.authority.host.address().contains("etro")) {
|
val uri = parser.uri(url, id)
|
||||||
(Etro.idParser(_, _), Etro.uri(url, id))
|
sendRequest(uri, BisProvider.parseBisJsonToPieces(job, parser, getPieceType))
|
||||||
} else {
|
|
||||||
(Ariyala.idParser(_, _), Ariyala.uri(url, id))
|
|
||||||
}
|
|
||||||
|
|
||||||
sendRequest(uri, BisProvider.parseBisJsonToPieces(job, idParser, getPieceType))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,11 +59,11 @@ object BisProvider {
|
|||||||
Behaviors.setup[BiSProviderMessage](context => new BisProvider(context))
|
Behaviors.setup[BiSProviderMessage](context => new BisProvider(context))
|
||||||
|
|
||||||
private def parseBisJsonToPieces(job: Job.Job,
|
private def parseBisJsonToPieces(job: Job.Job,
|
||||||
idParser: (Job.Job, JsObject) => Future[Map[String, Long]],
|
idParser: IdParser,
|
||||||
pieceTypes: Seq[Long] => Future[Map[Long, PieceType.PieceType]])
|
pieceTypes: Seq[Long] => Future[Map[Long, PieceType.PieceType]])
|
||||||
(js: JsObject)
|
(js: JsObject)
|
||||||
(implicit executionContext: ExecutionContext): Future[Seq[Piece]] =
|
(implicit executionContext: ExecutionContext): Future[Seq[Piece]] =
|
||||||
idParser(job, js).flatMap { pieces =>
|
idParser.parse(job, js).flatMap { pieces =>
|
||||||
pieceTypes(pieces.values.toSeq).map { types =>
|
pieceTypes(pieces.values.toSeq).map { types =>
|
||||||
pieces.view.mapValues(types).map {
|
pieces.view.mapValues(types).map {
|
||||||
case (piece, pieceType) => Piece(piece, pieceType, job)
|
case (piece, pieceType) => Piece(piece, pieceType, job)
|
||||||
|
@ -10,14 +10,14 @@ package me.arcanis.ffxivbis.service.bis
|
|||||||
|
|
||||||
import akka.http.scaladsl.model.Uri
|
import akka.http.scaladsl.model.Uri
|
||||||
import me.arcanis.ffxivbis.models.Job
|
import me.arcanis.ffxivbis.models.Job
|
||||||
import spray.json.{JsNumber, JsObject}
|
import spray.json.{JsNumber, JsObject, deserializationError}
|
||||||
|
|
||||||
import scala.concurrent.{ExecutionContext, Future}
|
import scala.concurrent.{ExecutionContext, Future}
|
||||||
|
|
||||||
object Etro {
|
object Etro extends IdParser {
|
||||||
|
|
||||||
def idParser(job: Job.Job, js: JsObject)
|
override def parse(job: Job.Job, js: JsObject)
|
||||||
(implicit executionContext: ExecutionContext): Future[Map[String, Long]] =
|
(implicit executionContext: ExecutionContext): Future[Map[String, Long]] =
|
||||||
Future {
|
Future {
|
||||||
js.fields.foldLeft(Map.empty[String, Long]) {
|
js.fields.foldLeft(Map.empty[String, Long]) {
|
||||||
case (acc, (key, JsNumber(id))) => BisProvider.remapKey(key).map(k => acc + (k -> id.toLong)).getOrElse(acc)
|
case (acc, (key, JsNumber(id))) => BisProvider.remapKey(key).map(k => acc + (k -> id.toLong)).getOrElse(acc)
|
||||||
@ -25,6 +25,6 @@ object Etro {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def uri(root: Uri, id: String): Uri =
|
override def uri(root: Uri, id: String): Uri =
|
||||||
root.withPath(Uri.Path / "api" / "gearsets" / id)
|
root.withPath(Uri.Path / "api" / "gearsets" / id)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
package me.arcanis.ffxivbis.service.bis
|
||||||
|
|
||||||
|
import akka.http.scaladsl.model.Uri
|
||||||
|
import com.typesafe.scalalogging.StrictLogging
|
||||||
|
import me.arcanis.ffxivbis.models.Job
|
||||||
|
import spray.json.JsObject
|
||||||
|
|
||||||
|
import scala.concurrent.{ExecutionContext, Future}
|
||||||
|
|
||||||
|
trait IdParser extends StrictLogging {
|
||||||
|
|
||||||
|
def parse(job: Job.Job, js: JsObject)
|
||||||
|
(implicit executionContext: ExecutionContext): Future[Map[String, Long]]
|
||||||
|
|
||||||
|
def uri(root: Uri, id: String): Uri
|
||||||
|
}
|
@ -70,7 +70,7 @@ object XivApi {
|
|||||||
js.fields("Results") match {
|
js.fields("Results") match {
|
||||||
case array: JsArray =>
|
case array: JsArray =>
|
||||||
array.elements.map(_.asJsObject.getFields("ID", "GameContentLinks") match {
|
array.elements.map(_.asJsObject.getFields("ID", "GameContentLinks") match {
|
||||||
case Seq(JsNumber(id), shop) => id.toLong -> extractTraderId(shop.asJsObject)
|
case Seq(JsNumber(id), shop: JsObject) => id.toLong -> extractTraderId(shop.asJsObject)
|
||||||
case other => throw deserializationError(s"Could not parse $other")
|
case other => throw deserializationError(s"Could not parse $other")
|
||||||
}).toMap
|
}).toMap
|
||||||
case other => throw deserializationError(s"Could not parse $other")
|
case other => throw deserializationError(s"Could not parse $other")
|
||||||
@ -83,18 +83,19 @@ object XivApi {
|
|||||||
Future {
|
Future {
|
||||||
val shopMap = js.fields("Results") match {
|
val shopMap = js.fields("Results") match {
|
||||||
case array: JsArray =>
|
case array: JsArray =>
|
||||||
array.elements.map { shop =>
|
array.elements.collect {
|
||||||
shop.asJsObject.fields("ID") match {
|
case shop: JsObject =>
|
||||||
case JsNumber(id) => id.toLong -> shop.asJsObject
|
shop.asJsObject.fields("ID") match {
|
||||||
case other => throw deserializationError(s"Could not parse $other")
|
case JsNumber(id) => id.toLong -> shop.asJsObject
|
||||||
}
|
case other => throw deserializationError(s"Could not parse $other")
|
||||||
|
}
|
||||||
}.toMap
|
}.toMap
|
||||||
case other => throw deserializationError(s"Could not parse $other")
|
case other => throw deserializationError(s"Could not parse $other")
|
||||||
}
|
}
|
||||||
|
|
||||||
shops.map { case (itemId, (index, shopId)) =>
|
shops.map { case (itemId, (index, shopId)) =>
|
||||||
val pieceType =
|
val pieceType =
|
||||||
if (index == "crafted" && shopId == -1) PieceType.Crafted
|
if (index == "crafted" && shopId == -1L) PieceType.Crafted
|
||||||
else {
|
else {
|
||||||
Try(shopMap(shopId).fields(s"ItemCost$index").asJsObject)
|
Try(shopMap(shopId).fields(s"ItemCost$index").asJsObject)
|
||||||
.toOption
|
.toOption
|
||||||
|
@ -33,11 +33,27 @@ object Fixtures {
|
|||||||
Ring(pieceType = PieceType.Savage, Job.DNC, "right ring")
|
Ring(pieceType = PieceType.Savage, Job.DNC, "right ring")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
lazy val bis3: BiS = BiS(
|
||||||
|
Seq(
|
||||||
|
Weapon(pieceType = PieceType.Savage ,Job.SGE),
|
||||||
|
Head(pieceType = PieceType.Tome, Job.SGE),
|
||||||
|
Body(pieceType = PieceType.Savage, Job.SGE),
|
||||||
|
Hands(pieceType = PieceType.Tome, Job.SGE),
|
||||||
|
Legs(pieceType = PieceType.Tome, Job.SGE),
|
||||||
|
Feet(pieceType = PieceType.Savage, Job.SGE),
|
||||||
|
Ears(pieceType = PieceType.Savage, Job.SGE),
|
||||||
|
Neck(pieceType = PieceType.Tome, Job.SGE),
|
||||||
|
Wrist(pieceType = PieceType.Savage, Job.SGE),
|
||||||
|
Ring(pieceType = PieceType.Savage, Job.SGE, "left ring"),
|
||||||
|
Ring(pieceType = PieceType.Tome, Job.SGE, "right ring")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
lazy val link: String = "https://ffxiv.ariyala.com/19V5R"
|
lazy val link: String = "https://ffxiv.ariyala.com/19V5R"
|
||||||
lazy val link2: String = "https://ffxiv.ariyala.com/1A0WM"
|
lazy val link2: String = "https://ffxiv.ariyala.com/1A0WM"
|
||||||
lazy val link3: String = "https://etro.gg/gearset/26a67536-b4ce-4adc-a46a-f70e348bb138"
|
lazy val link3: String = "https://etro.gg/gearset/26a67536-b4ce-4adc-a46a-f70e348bb138"
|
||||||
lazy val link4: String = "https://etro.gg/gearset/865fc886-994f-4c28-8fc1-4379f160a916"
|
lazy val link4: String = "https://etro.gg/gearset/865fc886-994f-4c28-8fc1-4379f160a916"
|
||||||
|
lazy val link5: String = "https://ffxiv.ariyala.com/1FGU0"
|
||||||
|
|
||||||
lazy val lootWeapon: Piece = Weapon(pieceType = PieceType.Tome, Job.AnyJob)
|
lazy val lootWeapon: Piece = Weapon(pieceType = PieceType.Tome, Job.AnyJob)
|
||||||
lazy val lootBody: Piece = Body(pieceType = PieceType.Savage, Job.AnyJob)
|
lazy val lootBody: Piece = Body(pieceType = PieceType.Savage, Job.AnyJob)
|
||||||
|
@ -23,6 +23,12 @@ class BisProviderTest extends ScalaTestWithActorTestKit(Settings.withRandomDatab
|
|||||||
probe.expectMessage(askTimeout, Fixtures.bis)
|
probe.expectMessage(askTimeout, Fixtures.bis)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"get best in slot set (ariyala 2)" in {
|
||||||
|
val probe = testKit.createTestProbe[BiS]()
|
||||||
|
provider ! DownloadBiS(Fixtures.link5, Job.SGE, probe.ref)
|
||||||
|
probe.expectMessage(askTimeout, Fixtures.bis3)
|
||||||
|
}
|
||||||
|
|
||||||
"get best in slot set (etro)" in {
|
"get best in slot set (etro)" in {
|
||||||
val probe = testKit.createTestProbe[BiS]()
|
val probe = testKit.createTestProbe[BiS]()
|
||||||
provider ! DownloadBiS(Fixtures.link3, Job.DNC, probe.ref)
|
provider ! DownloadBiS(Fixtures.link3, Job.DNC, probe.ref)
|
||||||
|
Loading…
Reference in New Issue
Block a user