Filter things out of the war base
当前为
// ==UserScript==
// @name Warbase Filters
// @namespace somenamespace
// @version 0.4
// @description Filter things out of the war base
// @author tos
// @include *.torn.com/factions.php?step=your*
// @grant GM_addStyle
// ==/UserScript==
animation_enabled = true
animation_duration = 5 //minutes
GM_addStyle(`
#wb_filter_wrap .arrow-wrap {display: block;}
#wb_filter_wrap i {margin: 8px 12px 0px 0px;}
#wb_filter_wrap .active i {margin: 11px 12px 0px 0px;}
#warbase_filters {
display: flex;}
#warbase_filters .wb_content_left {
display: inline-flex;
flex-direction: column;
padding: 5px;
width: 50%;
vertical-align: top;}
#warbase_filters .wb_content_right {
display: inline-flex;
flex-direction: column;
padding: 5px;
width: 50%;}
#warbase_filters .wbTotals_col_left{
display: inline-flex;
flex-direction: column;
font-size: 110%;
font-weight: bold;
width: auto;}
#warbase_filters .wbTotals_col_right{
display: inline-flex;
flex-direction: column;
font-size: 110%;
text-align: right;
font-weight: normal;
width: auto;}
#warbase_filters .wbTotals_title{
padding: 1px 0px 1px 10px;}
#warbase_filters .wbTotals {
padding: 1px 0px;}
#warbase_filters .filter-title {
display: inline-flex;
background-color: #BABABA;
border-radius: 5px 0px 0px 5px;
align-items: center;
font-size: 150%;
padding: 5px;
margin-bottom: 3px}
#warbase_filters .filter-content {
display: inline-flex;
flex-direction: column;
background-color: #DBDBDB;
border-radius: 0px 5px 5px 0px;
padding: 3px 0px;
margin-bottom: 3px}
#warbase_filters .filter-row {
display: flex;
flex-wrap: wrap;}
#warbase_filters span{
display: flex;
flex-wrap: wrap;
padding: 1px 10px;}
#warbase_filters input[type="checkbox"] {
margin-right: 3px;}
#warbase_filters input[type="number"] {
background: transparent;
border-bottom: 2px solid black;
text-align: center;
width: 50px;}
#warbase_filters .wb_counted {letter-spacing: 2px;}
.f-chain {border-radius: 14px}
@keyframes chainIconFade {
from {background-color: #b2b2b2;}
to {background-color: #f2f2f2;}}
.animation_colorfade {
animation-name: chainIconFade;
animation-duration: ${animation_duration * 60}s;}
#warbase_results {
display: none;}
#warbase_results .wbResults_placeholder {
font-weight: bold;
padding: 10px;}
#wars_extended {
margin-bottom:10px;}
#wars_extended .descriptions-new {
display: block;
margin: 0;
float: left;
background-color: transparent;
border-radius: 0;
box-shadow: none;
height: auto;
width: 100%;}
.wb_difficulty_select {
float: right;
height: 100%;
border: none;
background-color: inherit;
}
`)
let filters = JSON.parse(localStorage.getItem('torn_warbase_filters')) || {}
if(!filters.hasOwnProperty('fed')) filters.fed = false
if(!filters.hasOwnProperty('traveling')) filters.traveling = false
if(!filters.hasOwnProperty('jail')) filters.jail = false
if(!filters.hasOwnProperty('online')) filters.online = false
if(!filters.hasOwnProperty('idle')) filters.idle = false
if(!filters.hasOwnProperty('offline')) filters.offline = false
if(!filters.hasOwnProperty('hosp')) filters.hosp = false
if(!filters.hasOwnProperty('hosp_time')) filters.hosp_time = 0
if(!filters.hasOwnProperty('level')) filters.level = false
if(!filters.hasOwnProperty('level_min')) filters.level_min = 0
if(!filters.hasOwnProperty('level_max')) filters.level_max = 100
if(!filters.hasOwnProperty('extended')) filters.extended = false
if(!filters.hasOwnProperty('territories_inverted')) filters.territories_inverted = false
if(!filters.hasOwnProperty('filters_collapse')) filters.filters_collapse = false
let enemy_difficulty = JSON.parse(localStorage.getItem('torn_enemy_difficulties')) || {}
let faction_nodes = {}
let faction_totals = {}
const count_enemies = (obj) => {
let enemy_totals = {total:0, ok:0, hidden:0}
for (const factionID of Object.keys(obj)) {
enemy_totals.total += faction_totals[factionID].total
enemy_totals.ok += faction_totals[factionID].ok
enemy_totals.hidden += faction_totals[factionID].hidden
}
return enemy_totals
}
const run_filters = (node) => {
const factionID = node.querySelector('.t-blue').href.split('&')[1].replace('=', '')
let target_TOTALS = {total: 0, ok: 0, hidden: 0}
faction_totals[factionID] = {}
for (const enemy_LI of node.querySelector('.member-list').children) {
target_TOTALS.total += 1
const status = enemy_LI.querySelector('.status').firstElementChild.innerText
const online_status_icon = enemy_LI.querySelector('#icon1') || enemy_LI.querySelector('#icon2') || enemy_LI.querySelector('#icon62')
const online_status = online_status_icon.title.replace('<b>', '').replace('</b>', '')
//const bountied = enemy_LI.querySelector('#icon13') || false
//if(bountied) enemy_LI.style.backgroundColor ='#F0D9D2';
let hosp_time = 0
if (enemy_LI.querySelector('#icon15')) {
const time_string = enemy_LI.querySelector('#icon15').title.split('\'>')[1].split('</')[0]
hosp_time = parseInt(time_string.split(':')[0]) * 3600 + parseInt(time_string.split(':')[1]) * 60 + parseInt(time_string.split(':')[2])
}
let jail_time = 0
if (enemy_LI.querySelector('#icon16')) {
const time_string = enemy_LI.querySelector('#icon16').title.split('\'>')[1].split('</')[0]
jail_time = parseInt(time_string.split(':')[0]) * 3600 + parseInt(time_string.split(':')[1]) * 60 + parseInt(time_string.split(':')[2])
}
const level = parseInt(enemy_LI.querySelector('.lvl .t-hide').nextSibling.textContent)
const userID = enemy_LI.querySelector('.name').href.split('XID=')[1]
const li_icon_wrap = enemy_LI.querySelector('.member-icons')
const difficulty_select = document.createElement('SELECT')
difficulty_select.className = 'wb_difficulty_select'
difficulty_select.innerHTML = `
<option value="initial">Select Difficulty</option>
<option value="#def0d2">Easy</option>
<option value="#f0edd2">Med</option>
<option value="#F0D9D2">Hard</option>`
if (enemy_difficulty['ID_'+ userID]) {
difficulty_select.value = enemy_difficulty['ID_'+ userID]
enemy_LI.style.backgroundColor = enemy_difficulty['ID_'+ userID]
}
li_icon_wrap.append(difficulty_select)
difficulty_select.addEventListener('change', (event) => {
const profile_link = enemy_LI.querySelector('.name').href.split('torn.com')[1]
enemy_difficulty['ID_'+ userID] = event.target.value
for (const user_link of document.querySelectorAll('.member .t-hide a[href="'+profile_link+'"]')) {
user_link.parentElement.parentElement.parentElement.querySelector('.wb_difficulty_select').value = event.target.value
user_link.parentElement.parentElement.parentElement.style.backgroundColor = event.target.value
}
if (event.target.value === 'initial') delete enemy_difficulty['ID_'+ userID]
localStorage.setItem('torn_enemy_difficulties', JSON.stringify(enemy_difficulty))
})
if (status === 'Okay') target_TOTALS.ok +=1
if (filters.fed && status === 'Federal') enemy_LI.style.display = 'none'
else if (filters.traveling && status === 'Traveling') enemy_LI.style.display = 'none'
else if (filters.jail && filters.hosp_time * 60 < jail_time) enemy_LI.style.display = 'none'
else if (filters.online && online_status === 'Online') enemy_LI.style.display = 'none'
else if (filters.idle && online_status === 'Idle') enemy_LI.style.display = 'none'
else if (filters.offline && online_status === 'Offline') enemy_LI.style.display = 'none'
else if (filters.hosp && filters.hosp_time * 60 < hosp_time) enemy_LI.style.display = 'none'
else if (filters.level && (filters.level_min > level || filters.level_max < level)) enemy_LI.style.display = 'none'
else enemy_LI.style.display = 'list-item'
if (enemy_LI.style.display === 'none') target_TOTALS.hidden += 1
}
faction_totals[factionID].total = target_TOTALS.total
faction_totals[factionID].ok = target_TOTALS.ok
faction_totals[factionID].hidden = target_TOTALS.total - target_TOTALS.hidden
const warbase_totals = count_enemies(faction_totals)
for (const totals_span of document.querySelectorAll('.wbTotals')) {
const totals_controls = totals_span.className.split('wb_')[1]
if (totals_controls === 'counted') totals_span.innerText = Object.keys(faction_totals).length +'/'+ totals_span.innerText.split('/')[1]
else totals_span.innerText = warbase_totals[totals_controls]
}
}
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
if (node.className && node.className === 'faction-respect-wars-wp' && !document.querySelector('#wb_filter_wrap')) {
const faction_main_wrap = document.querySelector('#faction-main')
const respect_wars_wrap = document.querySelector('#faction-main .faction-respect-wars-wp')
const territory_wrap = document.querySelector('#faction-wars-wp')
let fac_count_total = 0
for (const faction_tab of respect_wars_wrap.querySelector('.f-war-list').children) {
if (faction_tab.className !== 'inactive' && faction_tab.className !== 'clear') fac_count_total += 1
}
//Filter DIV-------------------------------------------------------------------------------------------------------------------------------------
const filter_DIV = document.createElement('DIV')
filter_DIV.id = 'wb_filter_wrap'
filter_DIV.innerHTML =
`<div class="title-black m-top10 ${filters.filters_collapse ? 'border-round': 'top-round active' }">
<div class="arrow-wrap">
<i class="accordion-header-arrow right"></i>
</div>
War Base Filters
</div>
<div class="cont-gray map-wrap bottom-round " id="warbase_filters">
<div class="wb_content_left">
<div class="filter-row">
<div class="filter-title">Hide</div>
<div class="filter-content">
<div class="filter-row">
<span><input type="checkbox" class="wbFilter wb_fed">Federal</span>
<span><input type="checkbox" class="wbFilter wb_traveling">Traveling</span>
<span><input type="checkbox" class="wbFilter wb_jail">Jail</span>
</div>
<div class="filter-row">
<span><input type="checkbox" class="wbFilter wb_online">Online</span>
<span><input type="checkbox" class="wbFilter wb_idle">Idle</span>
<span><input type="checkbox" class="wbFilter wb_offline">Offline</span>
</div>
</div>
</div>
<div class="filter-row">
<div class="filter-title">Show</div>
<div class="filter-content">
<span class="filter-row"><input type="checkbox" class="wbFilter wb_hosp">Hosp time < <input type="number" class="wbFilter wb_hosp_time"> minutes</span>
<span class="filter-row"><input type="checkbox" class="wbFilter wb_level">Level<input type="number" min="0" max="100" class="wbFilter wb_level_min">to<input type="number" min="0" max="100" class="wbFilter wb_level_max"></span>
</div>
</div>
</div>
<div class="wb_content_right">
<div class="filter_row">
<div class="wbTotals_col_left">
<span class="filter-row wbTotals_title">Factions Counted: </span>
<span class="filter-row wbTotals_title">War Base Total: </span>
<span class="filter-row wbTotals_title">Status Okay Now: </span>
<span class="filter-row wbTotals_title">Filter Results: </span>
</div>
<div class="wbTotals_col_right">
<span class="filter-row wbTotals wb_counted">0/${fac_count_total}</span>
<span class="filter-row wbTotals wb_total">...</span>
<span class="filter-row wbTotals wb_ok">...</span>
<span class="filter-row wbTotals wb_hidden">...</span>
</div>
</div>
<span class="filter-row"><input type="checkbox" class="wbFilter wb_extended">Extended Warbase</span>
<span class="filter-row"><input type="checkbox" class="wbFilter wb_territories_inverted">Territories on top</span>
</div>
</div>`
faction_main_wrap.insertBefore(filter_DIV, respect_wars_wrap)
//War Base Extended DIV------------------------------------------------------------------------------------------------------------------------------
const warlist_DIV = document.createElement('DIV')
warlist_DIV.id = 'warbase_results'
warlist_DIV.innerHTML =
`<div class="title-black m-top10 top-round">War Base Extended</div>
<div class="cont-gray map-wrap bottom-round">
<div class="wbResults_placeholder">Updates on faction tab clicks...</div>
<ul id="wars_extended" class="f-war-list war-old">
<li class="clear"></li>
</ul>
</div>`
faction_main_wrap.insertBefore(warlist_DIV, territory_wrap)
//Event Listeners for Filter DIV----------------------------------------------------------------------------------------------------------------------
const wb_filter_title = document.querySelector('#wb_filter_wrap .title-black')
const wb_filter_content = document.querySelector('#warbase_filters')
filters.filters_collapse ? wb_filter_content.style.display = 'none': wb_filter_content.style.display = 'flex'
wb_filter_title.addEventListener('click', (event) => {
if (filters.filters_collapse) {
wb_filter_title.classList.add('top-round')
wb_filter_title.classList.add('active')
wb_filter_title.classList.remove('border-round')
wb_filter_content.style.display = 'flex'
filters.filters_collapse = false
}
else {
wb_filter_title.classList.remove('top-round')
wb_filter_title.classList.remove('active')
wb_filter_title.classList.add('border-round')
wb_filter_content.style.display = 'none'
filters.filters_collapse = true
}
localStorage.setItem('torn_warbase_filters', JSON.stringify(filters))
})
const filter_inputs = document.querySelectorAll('.wbFilter')
for (const wbFilter of filter_inputs) {
const filter_controls = wbFilter.className.split('wb_')[1]
switch (wbFilter.type) {
case 'checkbox':
wbFilter.checked = filters[filter_controls]
wbFilter.addEventListener('change', (event) => {
filters[filter_controls] = event.target.checked
localStorage.setItem('torn_warbase_filters', JSON.stringify(filters))
switch (filter_controls) {
case 'extended':
if (event.target.checked) document.querySelector('#warbase_results').style.display = 'block'
else document.querySelector('#warbase_results').style.display = 'none'
break
case 'territories_inverted':
if (event.target.checked) faction_main_wrap.insertBefore(territory_wrap, respect_wars_wrap)
else {
faction_main_wrap.insertBefore(respect_wars_wrap, territory_wrap)
faction_main_wrap.insertBefore(document.querySelector('#warbase_results'), territory_wrap)
}
break
default:
if (document.querySelector('#faction-main .faction-respect-wars-wp .descriptions')) {
run_filters(document.querySelector('#faction-main .faction-respect-wars-wp .descriptions'))
}
if (Object.keys(faction_nodes).length > 0) {
for (const facID of Object.keys(faction_nodes)) {
run_filters(faction_nodes[facID])
}
}
break
}
})
break
case 'number':
wbFilter.value = filters[filter_controls]
wbFilter.addEventListener('change', (event) => {
filters[filter_controls] = event.target.value
localStorage.setItem('torn_warbase_filters', JSON.stringify(filters))
switch (filter_controls) {
default:
if (document.querySelector('#faction-main .faction-respect-wars-wp .descriptions')) {
run_filters(document.querySelector('#faction-main .faction-respect-wars-wp .descriptions'))
}
if (Object.keys(faction_nodes).length > 0) {
for (const facID of Object.keys(faction_nodes)) {
run_filters(faction_nodes[facID])
}
}
break
}
})
break
default:
break
}
}
//Set Extended and Territories inverted--------------------------------------------------------------------------------------------------------------------
if (filters.extended) warlist_DIV.style.display = 'block'
if (filters.territories_inverted) faction_main_wrap.insertBefore(territory_wrap, respect_wars_wrap)
}
//Observing for tabs opening--------------------------------------------------------------------------------------------------------------------------------
if (node.className && node.className === 'descriptions') {
if (node.querySelector('.member-list')) {
const factionID = node.querySelector('.t-blue').href.split('&')[1].replace('=', '')
if (animation_enabled) {
const chain_icon = node.parentElement.querySelector('.act .f-chain')
if (chain_icon.className.includes('animation_colorfade')) {
chain_icon.classList.remove('animation_colorfade')
void chain_icon.offsetWidth
}
chain_icon.classList.add('animation_colorfade')
chain_icon.addEventListener("animationend", (anim) => anim.target.classList.remove('animation_colorfade'))
}
//clone node for extended war base
const wars_extended = document.querySelector('#wars_extended')
faction_nodes[factionID] = node.cloneNode(true)
faction_nodes[factionID].id = factionID
faction_nodes[factionID].className = 'descriptions-new'
run_filters(faction_nodes[factionID])
if (!document.querySelector('#'+factionID)) {
wars_extended.parentElement.querySelector('.wbResults_placeholder').style.display = 'none'
wars_extended.insertBefore(faction_nodes[factionID], wars_extended.lastElementChild)
}
else {
wars_extended.replaceChild(faction_nodes[factionID], document.querySelector('#'+factionID))
}
run_filters(node)
}
}
}
}
});
const wrapper = document.querySelector('#faction-main')
observer.observe(wrapper, { subtree: true, childList: true })