Coverage Summary for Class: HouseParser (com.galarzaa.tibiakt.core.section.community.house.parser)
| Class |
Class, %
|
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| HouseParser |
100%
(1/1)
|
100%
(3/3)
|
80%
(16/20)
|
95.8%
(46/48)
|
90.6%
(413/456)
|
/*
* Copyright © 2025 Allan Galarza
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.galarzaa.tibiakt.core.section.community.house.parser
import com.galarzaa.tibiakt.core.enums.StringEnum
import com.galarzaa.tibiakt.core.exceptions.ParsingException
import com.galarzaa.tibiakt.core.html.cells
import com.galarzaa.tibiakt.core.html.cleanText
import com.galarzaa.tibiakt.core.html.replaceBrs
import com.galarzaa.tibiakt.core.parser.Parser
import com.galarzaa.tibiakt.core.section.community.house.builder.HouseBuilder
import com.galarzaa.tibiakt.core.section.community.house.builder.house
import com.galarzaa.tibiakt.core.section.community.house.model.House
import com.galarzaa.tibiakt.core.section.community.house.model.HouseStatus
import com.galarzaa.tibiakt.core.text.clean
import com.galarzaa.tibiakt.core.text.findInteger
import com.galarzaa.tibiakt.core.text.parseInteger
import com.galarzaa.tibiakt.core.text.parseThousandSuffix
import com.galarzaa.tibiakt.core.text.remove
import com.galarzaa.tibiakt.core.time.parseTibiaDateTime
/** Parser for House information pages. */
public object HouseParser : Parser<House?> {
@Suppress("MaxLineLength")
private val rentedPattern =
Regex("""The (?<type>\w+) has been rented by (?<owner>[^.]+)\. (?<pronoun>\w+) has paid the rent until (?<paidUntil>[^.]+)\.""")
private val auctionedPattern = Regex("""The (?<type>\w+) is currently being auctioned.""")
@Suppress("MaxLineLength")
private val bidPattern =
Regex("""The auction will end at (?<auctionEnd>[^.]+)\. The highest bid so far is (?<highestBid>\d+) gold and has been submitted by (?<bidder>[^.]+)""")
private val moveOutPattern = Regex("""S?[Hh]e will move out on (?<moveDate>[^.]+) \(time of daily""")
@Suppress("MaxLineLength")
private val transferPattern =
Regex("""and (?<action>wants to|will) pass the house to (?<transferee>[\w\s]+) for (?<transferPrice>\d+) gold coin""")
override fun fromContent(content: String): House? {
val boxContent = boxContent(content)
val infoTable = boxContent.selectFirst("table")
return house {
val (imageRow, descriptionRow) = infoTable.cells()
if (imageRow.text().contains("No information about this house found")) return null
val imageUrl = imageRow.selectFirst("img")?.attr("src")
houseId = imageUrl?.findInteger() ?: throw ParsingException("House image not found")
val (title, sizeStr, rentStr, worldStr) = descriptionRow.select("b").map { it.cleanText() }
name = title
size = sizeStr.remove("square meters").clean().toInt()
rent = rentStr.remove("gold").parseThousandSuffix()
world = worldStr
val descriptionLines = descriptionRow.replaceBrs().wholeText().lines()
beds = descriptionLines[1].findInteger()
val statusLine = descriptionLines.last().clean()
parseStatusDescription(statusLine)
}
}
private fun HouseBuilder.parseStatusDescription(stateLine: String) {
rentedPattern.find(stateLine)?.apply {
status = HouseStatus.RENTED
ownerName = groups["owner"]!!.value.clean()
paidUntil = parseTibiaDateTime(groups["paidUntil"]!!.value)
houseType = StringEnum.fromValue("${groups["type"]!!.value}s")
?: throw ParsingException("Unknown house type found: ${groups["type"]!!.value}")
}
auctionedPattern.find(stateLine)?.apply {
status = HouseStatus.AUCTIONED
houseType = StringEnum.fromValue("${groups["type"]!!.value}s")
?: throw ParsingException("Unknown house type found: ${groups["type"]!!.value}")
}
bidPattern.find(stateLine)?.apply {
status = HouseStatus.AUCTIONED
auctionEndsAt = parseTibiaDateTime(groups["auctionEnd"]!!.value)
highestBid = groups["highestBid"]!!.value.parseInteger()
highestBidder = groups["bidder"]!!.value.clean()
}
moveOutPattern.find(stateLine)?.apply {
transferScheduledAt = parseTibiaDateTime(groups["moveDate"]!!.value)
}
transferPattern.find(stateLine)?.apply {
isTransferAccepted = groups["action"]!!.value == "will"
transferRecipient = groups["transferee"]!!.value.clean()
transferPrice = groups["transferPrice"]!!.value.toInt()
}
}
}