async function doPriceDiscovery(ns) {
    if (verbose) log(ns, ``);
    if (verbose) log(ns, `Doing price discovery for products.`);
    myCorporation = ns.corporation.getCorporation();
    for (const division of myCorporation.divisions) {
        const industry = industries.find((i) => i.name === division.type);
        // If we have Market-TA.II researched, just let that work.
        let hasMarketTA2 = ns.corporation.hasResearched(division.name, 'Market-TA.II');
        if (hasMarketTA2) {
            for (const city of division.cities) {
                // Default prices
                industry.prodMats.forEach((material) => ns.corporation.sellMaterial(division.name, city, material, 'MAX', 'MP'));
                division.products.forEach((product) => ns.corporation.sellProduct(division.name, city, product, 'MAX', 'MP'));
                // Turn on automation.
                industry.prodMats.forEach((material) => ns.corporation.setMaterialMarketTA2(division.name, city, material, true));
                division.products.forEach((product) => ns.corporation.setProductMarketTA2(division.name, product, true));
            }
            // No need to do any other price discovery on this division.
            continue;
        }

        // Materials are easy. Just sell them for Market price.
        for (const materialName of industry.prodMats) {
            for (const city of division.cities) {
                ns.corporation.sellMaterial(division.name, city, materialName, 'MAX', 'MP');
            }
        }

        // Go through each product, and see if the price needs to be adjusted. We can only
        // adjust the price on a per-product basis (desipe the UI letting you do it
        // manually, the API is busted.)
        let prevProductMultiplier = 1.0;
        for (const productName of division.products) {
            const product = ns.corporation.getProduct(division.name, productName);
            if (product.developmentProgress < 100) continue;
            let sPrice = product.sCost;
            // sPrice ought to be of the form 'MP * 123.45'. If not, we should use the price of the last product we calculated.
            let lastPriceMultiplier = prevProductMultiplier;
            try {
                let sMult = sPrice.split('*')[1];
                lastPriceMultiplier = Number.parseFloat(sMult);
            } catch {}
            let votes = [];
            for (const city of division.cities) {
                // Each city is going to "vote" for how they want the price to be manipulated.
                let qty = product.cityData[city][0];
                let produced = product.cityData[city][1];
                let sold = product.cityData[city][2];
                // if (verbose) log(ns, `${division.name}/${city}:${product.name} (qty, prod, sold): ` + product.cityData[city].map((n) => nf(n)));

                if (produced == sold && qty == 0) {
                    // We sold every item we produced. Vote to double the price.
                    votes.push(lastPriceMultiplier * 2);
                }
                // If we've accumulated a big stockpile, reduce our prices.
                else if (qty > produced * 100) {
                    votes.push(lastPriceMultiplier * 0.9);
                } else if (qty > produced * 40) {
                    votes.push(lastPriceMultiplier * 0.95);
                } else if (qty > produced * 20) {
                    votes.push(lastPriceMultiplier * 0.98);
                }
                // Our stock levels must be good. If we sold less than production, then our price is probably high
                else if (sold < produced) {
                    let newMultiplier = lastPriceMultiplier;
                    if (sold <= produced * 0.5) {
                        newMultiplier *= 0.75; // Our price is very high.
                    } else if (sold <= produced * 0.9) {
                        newMultiplier *= 0.95; // Our price is a bit high.
                    } else {
                        newMultiplier *= 0.99; // Our price is just barely high
                    }
                    votes.push(newMultiplier);
                }
                // If we sold more than production, then our price is probably low.
                else if (produced < sold) {
                    let newMultiplier = lastPriceMultiplier;
                    if (sold >= produced * 2) {
                        newMultiplier *= 2; // We sold way too much. Double the price.
                    } else if (sold >= produced * 1.33) {
                        newMultiplier *= 1.05; // We sold a bit too much. Bring the price up a bit.
                    } else {
                        newMultiplier *= 1.01;
                    }
                    votes.push(newMultiplier);
                }
            } // end for-cities
            // All of the cities have voted. Use the lowest price that the cities have asked for.
            votes.sort((a, b) => a - b);
            let newMultiplier = votes[0];
            let newPrice = `MP*${newMultiplier.toFixed(3)}`;
            // if (verbose) log(ns, `${prefix}Votes: ${votes.map((n) => nf(n)).join(', ')}.`);
            let sChange = percentChange(lastPriceMultiplier, newMultiplier);
            if (verbose) log(ns, `    Adjusting '${product.name}' price from ${sPrice} to ${newPrice} (${sChange}).`);
            ns.corporation.sellProduct(division.name, hqCity, product.name, 'MAX', newPrice, true);
            prevProductMultiplier = newMultiplier;
        } // end for-products
    } // end for-divisions
    if (verbose) log(ns, ``);
}
/**
 * Attempt to find a reasonablly stable price for each product. This will take several production cycles to stabilize.
 * @param {NS} ns
 */
Attempt to find a reasonablly stable price for each product. This will take several production cycles to stabilize.
@param {NS} ns
Attempt to find a reasonablly stable price for each product . This will take several production cycles to stabilize . @param { NS } ns
async function doPriceDiscovery(ns) {
    if (verbose) log(ns, ``);
    if (verbose) log(ns, `Doing price discovery for products.`);
    myCorporation = ns.corporation.getCorporation();
    for (const division of myCorporation.divisions) {
        const industry = industries.find((i) => i.name === division.type);
        let hasMarketTA2 = ns.corporation.hasResearched(division.name, 'Market-TA.II');
        if (hasMarketTA2) {
            for (const city of division.cities) {
                industry.prodMats.forEach((material) => ns.corporation.sellMaterial(division.name, city, material, 'MAX', 'MP'));
                division.products.forEach((product) => ns.corporation.sellProduct(division.name, city, product, 'MAX', 'MP'));
                industry.prodMats.forEach((material) => ns.corporation.setMaterialMarketTA2(division.name, city, material, true));
                division.products.forEach((product) => ns.corporation.setProductMarketTA2(division.name, product, true));
            }
            continue;
        }
        for (const materialName of industry.prodMats) {
            for (const city of division.cities) {
                ns.corporation.sellMaterial(division.name, city, materialName, 'MAX', 'MP');
            }
        }
        let prevProductMultiplier = 1.0;
        for (const productName of division.products) {
            const product = ns.corporation.getProduct(division.name, productName);
            if (product.developmentProgress < 100) continue;
            let sPrice = product.sCost;
            let lastPriceMultiplier = prevProductMultiplier;
            try {
                let sMult = sPrice.split('*')[1];
                lastPriceMultiplier = Number.parseFloat(sMult);
            } catch {}
            let votes = [];
            for (const city of division.cities) {
                let qty = product.cityData[city][0];
                let produced = product.cityData[city][1];
                let sold = product.cityData[city][2];
                if (produced == sold && qty == 0) {
                    votes.push(lastPriceMultiplier * 2);
                }
                else if (qty > produced * 100) {
                    votes.push(lastPriceMultiplier * 0.9);
                } else if (qty > produced * 40) {
                    votes.push(lastPriceMultiplier * 0.95);
                } else if (qty > produced * 20) {
                    votes.push(lastPriceMultiplier * 0.98);
                }
                else if (sold < produced) {
                    let newMultiplier = lastPriceMultiplier;
                    if (sold <= produced * 0.5) {
                        newMultiplier *= 0.75; 
                    } else if (sold <= produced * 0.9) {
                        newMultiplier *= 0.95; 
                    } else {
                        newMultiplier *= 0.99; 
                    }
                    votes.push(newMultiplier);
                }
                else if (produced < sold) {
                    let newMultiplier = lastPriceMultiplier;
                    if (sold >= produced * 2) {
                        newMultiplier *= 2; 
                    } else if (sold >= produced * 1.33) {
                        newMultiplier *= 1.05; 
                    } else {
                        newMultiplier *= 1.01;
                    }
                    votes.push(newMultiplier);
                }
            } 
            votes.sort((a, b) => a - b);
            let newMultiplier = votes[0];
            let newPrice = `MP*${newMultiplier.toFixed(3)}`;
            let sChange = percentChange(lastPriceMultiplier, newMultiplier);
            if (verbose) log(ns, `    Adjusting '${product.name}' price from ${sPrice} to ${newPrice} (${sChange}).`);
            ns.corporation.sellProduct(division.name, hqCity, product.name, 'MAX', newPrice, true);
            prevProductMultiplier = newMultiplier;
        } 
    } 
    if (verbose) log(ns, ``);
}
async function doPriceDiscovery ( ns ) { if ( verbose ) log ( ns , ` ` ) ; if ( verbose ) log ( ns , ` ` ) ; myCorporation = ns . corporation . getCorporation ( ) ; for ( const division of myCorporation . divisions ) { const industry = industries . find ( ( i ) => i . name === division . type ) ; let hasMarketTA2 = ns . corporation . hasResearched ( division . name , 'Market-TA.II' ) ; if ( hasMarketTA2 ) { for ( const city of division . cities ) { industry . prodMats . forEach ( ( material ) => ns . corporation . sellMaterial ( division . name , city , material , 'MAX' , 'MP' ) ) ; division . products . forEach ( ( product ) => ns . corporation . sellProduct ( division . name , city , product , 'MAX' , 'MP' ) ) ; industry . prodMats . forEach ( ( material ) => ns . corporation . setMaterialMarketTA2 ( division . name , city , material , true ) ) ; division . products . forEach ( ( product ) => ns . corporation . setProductMarketTA2 ( division . name , product , true ) ) ; } continue ; } for ( const materialName of industry . prodMats ) { for ( const city of division . cities ) { ns . corporation . sellMaterial ( division . name , city , materialName , 'MAX' , 'MP' ) ; } } let prevProductMultiplier = 1.0 ; for ( const productName of division . products ) { const product = ns . corporation . getProduct ( division . name , productName ) ; if ( product . developmentProgress < 100 ) continue ; let sPrice = product . sCost ; let lastPriceMultiplier = prevProductMultiplier ; try { let sMult = sPrice . split ( '*' ) [ 1 ] ; lastPriceMultiplier = Number . parseFloat ( sMult ) ; } catch { } let votes = [ ] ; for ( const city of division . cities ) { let qty = product . cityData [ city ] [ 0 ] ; let produced = product . cityData [ city ] [ 1 ] ; let sold = product . cityData [ city ] [ 2 ] ; if ( produced == sold && qty == 0 ) { votes . push ( lastPriceMultiplier * 2 ) ; } else if ( qty > produced * 100 ) { votes . push ( lastPriceMultiplier * 0.9 ) ; } else if ( qty > produced * 40 ) { votes . push ( lastPriceMultiplier * 0.95 ) ; } else if ( qty > produced * 20 ) { votes . push ( lastPriceMultiplier * 0.98 ) ; } else if ( sold < produced ) { let newMultiplier = lastPriceMultiplier ; if ( sold <= produced * 0.5 ) { newMultiplier *= 0.75 ; } else if ( sold <= produced * 0.9 ) { newMultiplier *= 0.95 ; } else { newMultiplier *= 0.99 ; } votes . push ( newMultiplier ) ; } else if ( produced < sold ) { let newMultiplier = lastPriceMultiplier ; if ( sold >= produced * 2 ) { newMultiplier *= 2 ; } else if ( sold >= produced * 1.33 ) { newMultiplier *= 1.05 ; } else { newMultiplier *= 1.01 ; } votes . push ( newMultiplier ) ; } } votes . sort ( ( a , b ) => a - b ) ; let newMultiplier = votes [ 0 ] ; let newPrice = ` ${ newMultiplier . toFixed ( 3 ) } ` ; let sChange = percentChange ( lastPriceMultiplier , newMultiplier ) ; if ( verbose ) log ( ns , ` ${ product . name } ${ sPrice } ${ newPrice } ${ sChange } ` ) ; ns . corporation . sellProduct ( division . name , hqCity , product . name , 'MAX' , newPrice , true ) ; prevProductMultiplier = newMultiplier ; } } if ( verbose ) log ( ns , ` ` ) ; }
Attempt to find a reasonablly stable price for each product.
Attempt to find a reasonablly stable price for each product .
// If we have Market-TA.II researched, just let that work.
 // Default prices
 // Turn on automation.
 // No need to do any other price discovery on this division.
 // Materials are easy. Just sell them for Market price.
 // Go through each product, and see if the price needs to be adjusted. We can only
 // adjust the price on a per-product basis (desipe the UI letting you do it
 // manually, the API is busted.)
 // sPrice ought to be of the form 'MP * 123.45'. If not, we should use the price of the last product we calculated.
 // Each city is going to "vote" for how they want the price to be manipulated.
 // if (verbose) log(ns, `${division.name}/${city}:${product.name} (qty, prod, sold): ` + product.cityData[city].map((n) => nf(n)));
 // We sold every item we produced. Vote to double the price.
 // If we've accumulated a big stockpile, reduce our prices.
 // Our stock levels must be good. If we sold less than production, then our price is probably high
 // Our price is very high.
 // Our price is a bit high.
 // Our price is just barely high
 // If we sold more than production, then our price is probably low.
 // We sold way too much. Double the price.
 // We sold a bit too much. Bring the price up a bit.
 // end for-cities
 // All of the cities have voted. Use the lowest price that the cities have asked for.
 // if (verbose) log(ns, `${prefix}Votes: ${votes.map((n) => nf(n)).join(', ')}.`);
 // end for-products
 // end for-divisions
