# BoobyLegends Economic Helper
This is intended as a helper to find trends in the Booby Legends game.
I intend to built a [Discord Bot Interface](DiscordBot.md) to let us share in our guild.
## Running Executables
### Gather Marketing Data
This will gather marketing data every 15 minutes, and build an average for each day in UTC timezone.
```bash
python3 gatherMarket.py
```
## Classes
There are some main components written as python classes.
### Market
Loads the current Market values for cards.
You can initialize the Market List like this:
```python
from market import Market
m=Market()
m.fetchData()
m.show()
```
Show a filtered Market Page with cards you alreqady have Crystalized removed.
```python
from market import Market
m=Market()
m.fetchData()
m.filterMarketCards(False)
#After doing stuff...
m.closePage()
```
### Player
Loads the current Player values for cards.
To get stock values, a "config.json" file must be in the folder with a "cookie" defined to have the player's login. I got my cookie by using the "EditThisCookie" plugin for Chrome. The config file should looks omething like this.
```json
{
"cookie":
{
"name":"wordpress_logged_in_f129834928365fbaer348384348y23423uy2323",
"value":"keymasterofgozer%8ksojhelFM88efn98709cvaSneOVWEUVn9dvs9eVASEvjSEv8ksojhelFM88efn98709cvaSneOVWEUVn9dvs9eVASEvjSEv8ksojhelFM88efn98709cvaSneOVW"
}
}
```
You can initialize your Player list like this:
```python
from player import Player
p=Player()
p.fetchData()
p.show()
```
Get a List of non-crystal remaining Cards to collect
```python
from player import Player
p=Player()
p.fetchData()
p.show(fields=['name','level','stock'],filter='stock != "CRYSTAL"')
```
### Market Data
```python
from db import MarketDB, hist, plot
hist(2)
plot(2)
```
### javascript to filter Market for needed cards
```javascript
clist=[];
for (var i = 0; i < 153; i++) {x={};x["extra"]=0;x["status"]="NORMAL";clist.push(x);}
let player = document.createElement('div');
player.id = 'player';
player.innerHTML=await (await fetch('https://play.boobylegends.com/player/')).text();
playerCards=player.getElementsByClassName('wrapper-card');
for (var i = 0; i < playerCards.length; i++) {
stock = {};
stock["extra"]=0;
stock["status"]="NORMAL";
try{
cardNum = parseInt(playerCards.item(i).getElementsByClassName('pornstar-number')[0].innerText);
var cardNB = cards.item(i).getElementsByClassName('card-nb')[0];
if (cardNB){try{
cnt = parseInt(cards.item(i).getElementsByClassName('nb-label')[0].outerText.trim());
stock["extra"]=cnt-1;
var fuzed = cards.item(i).getElementsByClassName('nb-name')[0];
if (fuzed){
stock["extra"] = stock["extra"] + 1;
stock["status"]= fuzed;
}
var priceDiv = cardNB.getElementsByClassName('Price')[0];
if (priceDiv){priceDiv.innerText = "Price: " + price;}
else{
let qty = document.createElement('div');
qty.classList.add('Price');
qty.innerText = "Price: " + price;
cardNB.appendChild(qty);
}
}catch(err){stock=stock;}}else{
stock=stock;
}
clist[cardNum]=stock;
}catch(err){console.log('hi');}
};
cards=document.getElementsByClassName('wrapper-market-card');
for (var i = 0; i < cards.length; i++) {
cardNum = cards.item(i).getElementsByClassName('pornstar-number')[0].outerText;
HTMLText = "Stock: " + clist[cardNum].status + " " + clist[cardNum].extra;
innerCard = cards.item(i).getElementsByClassName('inner-market-card')[0];
var stock = innerCard.getElementsByClassName('Stock')[0];
if (stock){stock.innerText = HTMLText}
else {
let qty = document.createElement('div');
qty.classList.add('Stock');
qty.innerText = HTMLText;
innerCard.appendChild(qty);
}
if (clist[cardNum].status == 'CRYSTAL'){
cards.item(i).style.setProperty('Display','None');
}
};
```
### javascript to filter Market for uncrystalized cards
```javascript
clist=[];
for (var i = 0; i < 153; i++) {clist.push(0);}
let player = document.createElement('div');
player.id = 'player';
player.innerHTML=await (await fetch('https://play.boobylegends.com/player/')).text();
playerCards=player.getElementsByClassName('wrapper-card');
for (var i = 0; i < playerCards.length; i++) {
try{
cardNum = parseInt(playerCards.item(i).getElementsByClassName('pornstar-number')[0].innerText);
stock = playerCards.item(i).getElementsByClassName('card-nb')[0].innerText.trim();
clist[cardNum]=stock;
}catch(err){console.log('hi');}
};
cards=document.getElementsByClassName('wrapper-market-card');
for (var i = 0; i < cards.length; i++) {
cardNum = cards.item(i).getElementsByClassName('pornstar-number')[0].outerText;
HTMLText = "Stock: " + clist[cardNum];
innerCard = cards.item(i).getElementsByClassName('inner-market-card')[0];
var stock = innerCard.getElementsByClassName('Stock')[0];
if (stock){stock.innerText = HTMLText}
else {
let qty = document.createElement('div');
qty.classList.add('Stock');
qty.innerText = HTMLText;
innerCard.appendChild(qty);
}
if (clist[cardNum].toString().includes('CRYSTAL')){
cards.item(i).style.setProperty('Display','None');
}
}
```
### javascript to filter Market for good value cards
```javascript
cards=document.getElementsByClassName('wrapper-market-card');
for (var i = 0; i < cards.length; i++) {
cardNum = cards.item(i).getElementsByClassName('pornstar-number')[0].outerText;
cardVal = parseInt(cards.item(i).getElementsByClassName('score-card')[0].outerText);
cardCost = parseInt(cards.item(i).getElementsByClassName('cost')[0].outerText);
cardPPG = cardVal/cardCost;
HTMLText = "Points/:
" + cardPPG.toFixed(2);
innerCard = cards.item(i).getElementsByClassName('inner-market-card')[0];
var PPG = innerCard.getElementsByClassName('PPG')[0];
if (PPG){PPG.innerHTML = HTMLText}
else {
let qty = document.createElement('div');
qty.classList.add('PPG');
qty.innerHTML = HTMLText;
qty.setAttribute("align", "center");
innerCard.appendChild(qty);
}
if (cardPPG < 2){
cards.item(i).style.setProperty('Display','None');
}
}
```
### javascript to filter Player Page for salable cards
```javascript
sellThreshold = {};
sellThreshold["2000"] = 10000;
sellThreshold["350"] = 195;
sellThreshold["250"] = 126;
sellThreshold["200"] = 87;
sellThreshold["150"] = 110;
sellThreshold["115"] = 80;
sellThreshold["75"] = 32;
sellThreshold["50"] = 25;
sellThreshold["40"] = 32;
sellThreshold["20"] = 22;
sellThreshold["15"] = 12;
sellThreshold["10"] = 8;
sellThreshold["4"] = 9;
sellThreshold["3"] = 4;
sellThreshold["2"] = 4;
sellThreshold["1"] = 4;
clist=[];
for (var i = 0; i < 153; i++) {clist.push(0);}
let market = document.createElement('div');
market.id = 'market';
market.innerHTML=await (await fetch('https://play.boobylegends.com/market/')).text();
marketCards=market.getElementsByClassName('wrapper-market-card');
for (var i = 0; i < marketCards.length; i++) {
try{
cardNum = parseInt(marketCards.item(i).getElementsByClassName('pornstar-number')[0].innerText);
price = parseInt(marketCards.item(i).getElementsByClassName('cost')[0].innerText.trim());
clist[cardNum]=price;
}catch(err){console.log('error on '+cardNum.toString());}
};
cards=document.getElementsByClassName('wrapper-card');
for (var i = 0; i < cards.length; i++) {
cardNum = parseInt(cards.item(i).getElementsByClassName('pornstar-number')[0].outerText);
cardVal = parseInt(cards.item(i).getElementsByClassName('score-card')[0].outerText);
price = clist[cardNum];
var cardNB = cards.item(i).getElementsByClassName('card-nb')[0];
if (cardNB){try{
stock = parseInt(cards.item(i).getElementsByClassName('nb-label')[0].outerText.trim());
var fuzed = cards.item(i).getElementsByClassName('nb-name')[0];
if (fuzed){stock = stock + 1;}
var priceDiv = cardNB.getElementsByClassName('Price')[0];
if (priceDiv){priceDiv.innerText = "Price: " + price;}
else{
let qty = document.createElement('div');
qty.classList.add('Price');
qty.innerText = "Price: " + price;
cardNB.appendChild(qty);
}
}catch(err){stock=0;}}else{
stock=0;
}
if (stock<2){
cards.item(i).style.setProperty('Display','None');
}
if (priceThreshold: "+sellThreshold[cardVal.toString()];
innerCard = cards.item(i).getElementsByClassName('inner-market-card')[0];
var PPG = innerCard.getElementsByClassName('PPG')[0];
if (PPG){PPG.innerHTML = HTMLText}
else {
let qty = document.createElement('div');
qty.classList.add('PPG');
qty.innerHTML = HTMLText;
qty.setAttribute("align", "center");
innerCard.appendChild(qty);
}
if (cardCost <= clist[cardNum]){
cards.item(i).style.setProperty('Display','None');
}
if (clist[cardNum] < sellThreshold[cardVal.toString()]){
cards.item(i).style.setProperty('Display','None');
}
}
```