another test for bis part

This commit is contained in:
Evgenii Alekseev 2022-01-06 06:19:57 +03:00
parent 0ed9e92441
commit 99ed2705a2
11 changed files with 74 additions and 31 deletions

View File

@ -24,7 +24,7 @@ trait PlayerHelper extends BisProviderHelper {
def addPlayer(player: Player)
(implicit executionContext: ExecutionContext, timeout: Timeout, scheduler: Scheduler): Future[Unit] =
storage.ask(ref => AddPlayer(player, ref)).map { res =>
player.link match {
player.link.map(_.trim).filter(_.nonEmpty) match {
case Some(link) =>
downloadBiS(link, player.job).map { bis =>
bis.pieces.map(piece => storage.ask(AddPieceToBis(player.playerId, piece, _)))

View File

@ -74,7 +74,7 @@ class BiSView(override val storage: ActorRef[Message],
}
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", _) =>
bisAction(playerId, piece, pieceType)(addPieceBiS(playerId, _))
case (Some(piece), Some(pieceType), "remove", _) =>

View File

@ -89,6 +89,8 @@ object LootSuggestView {
body(
h2("Suggest loot"),
for (part <- piece) yield p(s"Piece ${part.piece} (${part.pieceType})"),
ErrorView.template(error),
SearchLineView.template,

View File

@ -5,4 +5,7 @@ import me.arcanis.ffxivbis.models.{BiS, Job}
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")
}

View File

@ -14,10 +14,10 @@ import spray.json.{JsNumber, JsObject, JsString, deserializationError}
import scala.concurrent.{ExecutionContext, Future}
object Ariyala {
object Ariyala extends IdParser {
def idParser(job: Job.Job, js: JsObject)
(implicit executionContext: ExecutionContext): Future[Map[String, Long]] =
override def parse(job: Job.Job, js: JsObject)
(implicit executionContext: ExecutionContext): Future[Map[String, Long]] =
Future {
val apiJob = js.fields.get("content") match {
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
.withPath(Uri.Path / "store.app")
.withQuery(Uri.Query(Map("identifier" -> id)))

View File

@ -9,7 +9,6 @@
package me.arcanis.ffxivbis.service.bis
import java.nio.file.Paths
import akka.actor.ClassicActorSystemProvider
import akka.actor.typed.{Behavior, PostStop, Signal}
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 scala.concurrent.{ExecutionContext, Future}
import scala.util.{Failure, Success}
class BisProvider(context: ActorContext[BiSProviderMessage])
extends AbstractBehavior[BiSProviderMessage](context) with XivApi with StrictLogging {
@ -29,7 +29,11 @@ class BisProvider(context: ActorContext[BiSProviderMessage])
override def onMessage(msg: BiSProviderMessage): Behavior[BiSProviderMessage] =
msg match {
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
}
@ -43,14 +47,9 @@ class BisProvider(context: ActorContext[BiSProviderMessage])
val url = Uri(link)
val id = Paths.get(link).normalize.getFileName.toString
val (idParser, uri) =
if (url.authority.host.address().contains("etro")) {
(Etro.idParser(_, _), Etro.uri(url, id))
} else {
(Ariyala.idParser(_, _), Ariyala.uri(url, id))
}
sendRequest(uri, BisProvider.parseBisJsonToPieces(job, idParser, getPieceType))
val parser = if (url.authority.host.address().contains("etro")) Etro else Ariyala
val uri = parser.uri(url, id)
sendRequest(uri, BisProvider.parseBisJsonToPieces(job, parser, getPieceType))
}
}
@ -60,11 +59,11 @@ object BisProvider {
Behaviors.setup[BiSProviderMessage](context => new BisProvider(context))
private def parseBisJsonToPieces(job: Job.Job,
idParser: (Job.Job, JsObject) => Future[Map[String, Long]],
idParser: IdParser,
pieceTypes: Seq[Long] => Future[Map[Long, PieceType.PieceType]])
(js: JsObject)
(implicit executionContext: ExecutionContext): Future[Seq[Piece]] =
idParser(job, js).flatMap { pieces =>
idParser.parse(job, js).flatMap { pieces =>
pieceTypes(pieces.values.toSeq).map { types =>
pieces.view.mapValues(types).map {
case (piece, pieceType) => Piece(piece, pieceType, job)

View File

@ -10,14 +10,14 @@ package me.arcanis.ffxivbis.service.bis
import akka.http.scaladsl.model.Uri
import me.arcanis.ffxivbis.models.Job
import spray.json.{JsNumber, JsObject}
import spray.json.{JsNumber, JsObject, deserializationError}
import scala.concurrent.{ExecutionContext, Future}
object Etro {
object Etro extends IdParser {
def idParser(job: Job.Job, js: JsObject)
(implicit executionContext: ExecutionContext): Future[Map[String, Long]] =
override def parse(job: Job.Job, js: JsObject)
(implicit executionContext: ExecutionContext): Future[Map[String, Long]] =
Future {
js.fields.foldLeft(Map.empty[String, Long]) {
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)
}

View File

@ -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
}

View File

@ -70,7 +70,7 @@ object XivApi {
js.fields("Results") match {
case array: JsArray =>
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")
}).toMap
case other => throw deserializationError(s"Could not parse $other")
@ -83,18 +83,19 @@ object XivApi {
Future {
val shopMap = js.fields("Results") match {
case array: JsArray =>
array.elements.map { shop =>
shop.asJsObject.fields("ID") match {
case JsNumber(id) => id.toLong -> shop.asJsObject
case other => throw deserializationError(s"Could not parse $other")
}
array.elements.collect {
case shop: JsObject =>
shop.asJsObject.fields("ID") match {
case JsNumber(id) => id.toLong -> shop.asJsObject
case other => throw deserializationError(s"Could not parse $other")
}
}.toMap
case other => throw deserializationError(s"Could not parse $other")
}
shops.map { case (itemId, (index, shopId)) =>
val pieceType =
if (index == "crafted" && shopId == -1) PieceType.Crafted
if (index == "crafted" && shopId == -1L) PieceType.Crafted
else {
Try(shopMap(shopId).fields(s"ItemCost$index").asJsObject)
.toOption

View File

@ -33,11 +33,27 @@ object Fixtures {
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 link2: String = "https://ffxiv.ariyala.com/1A0WM"
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 link5: String = "https://ffxiv.ariyala.com/1FGU0"
lazy val lootWeapon: Piece = Weapon(pieceType = PieceType.Tome, Job.AnyJob)
lazy val lootBody: Piece = Body(pieceType = PieceType.Savage, Job.AnyJob)

View File

@ -23,6 +23,12 @@ class BisProviderTest extends ScalaTestWithActorTestKit(Settings.withRandomDatab
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 {
val probe = testKit.createTestProbe[BiS]()
provider ! DownloadBiS(Fixtures.link3, Job.DNC, probe.ref)