Cost of owning vehicles/equipment - Optimal time to replace - Detailed cost analysis

humbe
Posts: 1415
Joined: Sat Jan 18, 2020 9:33 pm

Re: Cost of owning vehicles/equipment - Optimal time to replace - Detailed cost analysis

Post by humbe »

dan1109 wrote: Mon Jan 17, 2022 11:04 pm ...With the exception of usually poorer lighting, transmission options, and slower max speed, classic tractors are usually the best HP/$ value you can get in game.
Yeah.. A lot of the reasons why real farmers will prefer modern gear isn't reflected in the game. Only thing I can think of is if you play with a manual gearbox, I'd be willing to pay quite a bit extra for a Fendt Vario or some similarly nice transmission ;)
NDDan
Posts: 132
Joined: Sat Oct 16, 2021 4:11 am

Re: Cost of owning vehicles/equipment - Optimal time to replace - Detailed cost analysis

Post by NDDan »

humbe wrote: Mon Jan 17, 2022 10:57 pm Thanks for the positive comments ;)

Added a portion on used vehicles above. They are truely a bargain, as, possibly a bug, cause initial price to be set to the used price, so they are really cheap maintenance wise.
Yes, this is strange. If you buy something used for 50% off, the value of it immediately becomes 50% of what you just paid for it, so it’s already down to 25%. I agree that this seems like a bug.

Thanks for your great analysis.
There’s no place like utopia.
humbe
Posts: 1415
Joined: Sat Jan 18, 2020 9:33 pm

Re: Cost of owning vehicles/equipment - Optimal time to replace - Detailed cost analysis

Post by humbe »

NDDan wrote: Tue Jan 18, 2022 4:22 am ...
Yes, this is strange. If you buy something used for 50% off, the value of it immediately becomes 50% of what you just paid for it, so it’s already down to 25%. I agree that this seems like a bug.

Thanks for your great analysis.
Yes.. You buy something that already has age and operation time on it, which reduces sell value below the initial 12% of a new vehicle. The sell price mechanics are the same, so thus the value loss is more than 12%. Also, they typically already have paint damage and needs repair, and you don't get to know paint and maintenance condition before you buy it, so the real cost is a bit more due to having to repair it immediately to. The paint state doesn't really factor in as it wears of so fast anyhow.

One would think that if they kept the initial price as the new price, then the sell value would be correct, far less than 12% of what you bought it for, but it seems the buy value is far below what you can sell it for, so if that was the case, you could buy used gear, repair and repaint and then sell it with gain immediately. I guess that might be why they put in the rebated price there, because the sell value is too good to be true ;)

Oh.. And a note about the operation time cap of 50 hours before maintenance cost stops to increase further due to time used. I'm starting to think, as this drops of fairly quickly, that this is intended to just be a mechanic to indicate that new gear doesn't need much repairs.. And getting to the cap just means, now the vehicle is no longer new, so you're in steady state and will have to start replacing components as they wear out and so on.

I don't object with the price of maintenance after figuring out the details, but would be nice if they could increase the time interval between repairs and rather take more for each repair, so you at least could run through a few diesel tanks between each repair. Also.. Would be good to flatten the curve to begin with, so the optimal time to repair was at like 30-50% state rather than as soon as possible and as often as possible.
george.earlslight
Posts: 784
Joined: Tue Nov 20, 2018 11:45 am
Location: Europe

Re: Cost of owning vehicles/equipment - Optimal time to replace - Detailed cost analysis

Post by george.earlslight »

Hello, first off all thanks again for your effort on analyzing the maintenance game mechanics.
Out of respect for your work I've decided to post my own findings as a reply to your thread, commenting where I managed to make improvements.
I've split the analysis in parts.

Part 1. Damage taken over time

This is what I've found to be a very peculiar game decision by Giants, and a downgrade of previous game versions.
Vehicle damage accumulates as long as there's a driver on a vehicle (player or AI).
It doesn't matter if you turn the engine on and idle, if you're pulling a 20ton cultivator over mud, or just chilling admiring the views engine turned off.
As long as you're tabbed in a vehicle, it gets damaged.
Paint does get degraded depending on work and whether being on a field or on road.

Now on to the math.
Your formula is accurate as to the instantaneous damage rate. I'm going to add that it's also depended on a constant found on each vehicle's .xml

Code: Select all

<wearable wearDuration="480"
All base game vehicles have a wearDuration of 480 and it anyway doesn't have much influence on the final result.
A value of 48000 would lower the damage rate by 25%.
As such, the formula approximation is the following

Code: Select all

damageRate = (0.35 / (wearDuration/60))+(0.00298*operatingHours)
Image

The rate increase does cap at 50h, as you've mentioned.
It seems that the rate is a bit off as operating time increases, so there's probably more to it in the actual ingame formula.

Now I'm going to jump for a bit to your final conclusion.
When calculating monthly damage, it seems you've made your calculations having a constant rate of damage over operating time.
This is not correct, as the rate is not constant. You need to integrate over the range of operating time.
We could integrate using the analytical method, but this is not how the game works.
Image
The game engine calculates the new damage on every update tick and sums it up.
This is similar to calculating an integral using approximation.

I've written a python script to calculate this.

Code: Select all

def damageRate(wearDuration, operatingTime):
    if operatingTime > (3600*50):
        operatingTime = 3600*50
    return (0.35 / (wearDuration/60)) + (0.00289*(operatingTime/3600))

def damageDone(wearDuration, operatingTimeStart, operatingTimeEnd):
    totDamage = 0
    simTime = operatingTimeStart   
    while simTime < operatingTimeEnd:
        damage = damageRate(wearDuration, simTime) * (1/3600)
        totDamage = totDamage + damage
        simTime = simTime + 1
    return totDamage

for optime in range (1800,54000,1800):
    print(damageDone(480, optime-1800, optime))
The difference here is not trivial, as your results can be 15-20% less on the monthly maintenance cost and this is accumulating fast.
Image
The results are very close to what is stored in the vehicles.xml <wearable damage>
george.earlslight
Posts: 784
Joined: Tue Nov 20, 2018 11:45 am
Location: Europe

Re: Cost of owning vehicles/equipment - Optimal time to replace - Detailed cost analysis

Post by george.earlslight »

Part 2. Cost of repairs

My findings match yours exactly.
The formula seems correct as

Code: Select all

0.09*(damage^1.5)*price
I agree that this is overly simplistic, but I will summarize my comments on the last part.

Some more python scripts for testing.

Code: Select all

def repairCost(price, damage):
    return (0.09 * pow(damage, 1.5) * price)
    
def repairCostOverTime(price, wearDuration, operatingTimeStart, operatingTimeEnd):
    return (repairCost(price,damageDone(wearDuration, operatingTimeStart, operatingTimeEnd)))
george.earlslight
Posts: 784
Joined: Tue Nov 20, 2018 11:45 am
Location: Europe

Re: Cost of owning vehicles/equipment - Optimal time to replace - Detailed cost analysis

Post by george.earlslight »

Part 3. Devaluation

As you've mentioned, its clear that equipment loses value depending on operatingTime and age.
I've managed to calculate the individual part very close to the actual results, by keeping each part at zero one at a time, but the final result seems off.
Again, it seems there's something more in what Giants uses in their code.

Operating time devaluation is perfectly exact, as you've mentioned.
My addition to your findings is that I'm assuming Giants is caclulating always on the initial used price, the price with the 12% deduction.
So I've drawn my plots accordingly and it seems the formula is an exact match, along with what is probably written in game code.

Code: Select all

usedPrice=0.88*price

Code: Select all

sellPrice=(1-(5/3000*operatingHours)*usedPrice
Image

I've also managed to find the devaluation by age formula.
The value loss factor exactly matches the logarithmic function. Again, the plot is over the usedPrice.
Devaluation starts at 8 months in, anything less and the price is the initial used price.

Code: Select all

sellPrice=(1.25-(0.125*ln(age)))*usedPrice
Image
I'm having a constant error, which I didn't manage to find the source of.
Adjusting the function to

Code: Select all

sellPrice=1.25-(0.125*ln(age))-0.00189)*usedPrice
seems to completely eliminate the error.

Now plugging in both factors, age and operating time, should result in perfectly predicting the sale value.
But it's not. As age and operating time increases, it seems that there's also more to the formula. I didn't put much effort on trying to find out what's up
Image

Python script

Code: Select all

def sellValue(price, age, operatingTime):
    usedPrice = price * 0.88
    
    if age > 7:
        ageDevaluation = 1.25-(0.125*math.log(age))
    else:
        ageDevaluation = 1
    
    useDevaluation = (1-(5/3000*operatingTime/3600))
    
    return (usedPrice*ageDevaluation*useDevaluation)
george.earlslight
Posts: 784
Joined: Tue Nov 20, 2018 11:45 am
Location: Europe

Re: Cost of owning vehicles/equipment - Optimal time to replace - Detailed cost analysis

Post by george.earlslight »

Part 4. Deciding when to replace

Now this is the part where I'm trying to answer my initial question.
Could there be an optimal time to replace your equipment?

The short answer is it doesn't seem so.

But there can be a time when it's almost the same cost.
It's dependent on something most players don't know when playing, how many ingame years one is going to be in a single map.
Playing a map for 8 years, 10 years or 12 years, are all going to produce different results.
The other input is how many hours the tractor is going to work each year.
This is probably easier to predict, once you've played the game a bit.
My tractors are used about 12-16h per year.
One concession I had to make is to calculate the repair intervals as if repairing each work hour.
This is not something I always do, but it fits my play style the closest.
The python scripts can be adjusted to change the repair interval or restructured to repair at specific damage percentage.
Repairing at specific damage is not something I personally do.

On to the methodology, we first calculate the cost of ownership of a tractor we never replace.
As we plan to keep it forever, its sell price doesn't matter.
We only care about the increasing cost of maintenance.
Here's the script and an example result for the Fendt 1038 and playing on the map for 10 years.

Code: Select all

#assumes repair every hour, wearDuration = 480 as per Giants base
def costOfOwnershipKeep(price, opHoursPerYear, yearsToRunSim):
    sumCost = 0
    for hours in range (1, yearsToRunSim*opHoursPerYear):
        #print("--- Hour ", hours, "---")
        hourCost = repairCostOverTime(price, 480, (hours-1)*3600, hours*3600)
        #print("Hourly Cost ", hourCost)
        sumCost = sumCost + hourCost
    #print("---= Keep the equipment =---")
    #print("Total operating Cost ", sumCost)
    return sumCost
    
costOfOwnershipKeep(329000,16,10)

Code: Select all

--- Hour  1 ---
Hourly Cost  284.4907877464182
--- Hour  2 ---
Hourly Cost  312.210424689934
--- Hour  3 ---
Hourly Cost  340.77610086327354
--- Hour  4 ---
Hourly Cost  370.16346281333176
--- Hour  5 ---
Hourly Cost  400.3501468940273
--- Hour  6 ---
Hourly Cost  431.3155221572384
--- Hour  7 ---
Hourly Cost  463.0404774908134
--- Hour  8 ---
Hourly Cost  495.5072436679148
--- Hour  9 ---
Hourly Cost  528.6992432725746
--- Hour  10 ---
Hourly Cost  562.6009631254026
--- Hour  11 ---
Hourly Cost  597.1978450489814
--- Hour  12 ---
Hourly Cost  632.4761917158634
--- Hour  13 ---
Hourly Cost  668.423085002493
--- Hour  14 ---
Hourly Cost  705.0263147908387
--- Hour  15 ---
Hourly Cost  742.2743165590208
--- Hour  16 ---
Hourly Cost  780.1561164132092
--- Hour  17 ---
Hourly Cost  818.6612824573699
--- Hour  18 ---
Hourly Cost  857.7798815910962
--- Hour  19 ---
Hourly Cost  897.5024409804498
--- Hour  20 ---
Hourly Cost  937.8199135713081
--- Hour  21 ---
Hourly Cost  978.7236471156625
--- Hour  22 ---
Hourly Cost  1020.2053562637218
--- Hour  23 ---
Hourly Cost  1062.2570973423353
--- Hour  24 ---
Hourly Cost  1104.8712454961305
--- Hour  25 ---
Hourly Cost  1148.0404739141677
--- Hour  26 ---
Hourly Cost  1191.7577349036646
--- Hour  27 ---
Hourly Cost  1236.0162426048291
--- Hour  28 ---
Hourly Cost  1280.8094571682661
--- Hour  29 ---
Hourly Cost  1326.131070239554
--- Hour  30 ---
Hourly Cost  1371.9749916153376
--- Hour  31 ---
Hourly Cost  1418.3353369521449
--- Hour  32 ---
Hourly Cost  1465.2064164233996
--- Hour  33 ---
Hourly Cost  1512.5827242326895
--- Hour  34 ---
Hourly Cost  1560.4589289019073
--- Hour  35 ---
Hourly Cost  1608.8298642621169
--- Hour  36 ---
Hourly Cost  1657.6905210831587
--- Hour  37 ---
Hourly Cost  1707.036039284886
--- Hour  38 ---
Hourly Cost  1756.8617006790696
--- Hour  39 ---
Hourly Cost  1807.1629221963822
--- Hour  40 ---
Hourly Cost  1857.9352495575672
--- Hour  41 ---
Hourly Cost  1909.1743513520025
--- Hour  42 ---
Hourly Cost  1960.8760134905492
--- Hour  43 ---
Hourly Cost  2013.0361340028617
--- Hour  44 ---
Hourly Cost  2065.6507181520274
--- Hour  45 ---
Hourly Cost  2118.71587384217
--- Hour  46 ---
Hourly Cost  2172.227807296817
--- Hour  47 ---
Hourly Cost  2226.1828189877015
--- Hour  48 ---
Hourly Cost  2280.5772997958516
--- Hour  49 ---
Hourly Cost  2335.407727388032
--- Hour  50 ---
Hourly Cost  2390.6706627933236
--- Hour  51 ---
Hourly Cost  2418.4710032765515
--- Hour  52 ---
Hourly Cost  2418.4710032765515
--- Hour  53 ---
Hourly Cost  2418.4710032765515
--- Hour  54 ---
Hourly Cost  2418.4710032765515
--- Hour  55 ---
Hourly Cost  2418.4710032765515
--- Hour  56 ---
Hourly Cost  2418.4710032765515
--- Hour  57 ---
Hourly Cost  2418.4710032765515
--- Hour  58 ---
Hourly Cost  2418.4710032765515
--- Hour  59 ---
Hourly Cost  2418.4710032765515
--- Hour  60 ---
Hourly Cost  2418.4710032765515
--- Hour  61 ---
Hourly Cost  2418.4710032765515
--- Hour  62 ---
Hourly Cost  2418.4710032765515
--- Hour  63 ---
Hourly Cost  2418.4710032765515
--- Hour  64 ---
Hourly Cost  2418.4710032765515
--- Hour  65 ---
Hourly Cost  2418.4710032765515
--- Hour  66 ---
Hourly Cost  2418.4710032765515
--- Hour  67 ---
Hourly Cost  2418.4710032765515
--- Hour  68 ---
Hourly Cost  2418.4710032765515
--- Hour  69 ---
Hourly Cost  2418.4710032765515
--- Hour  70 ---
Hourly Cost  2418.4710032765515
--- Hour  71 ---
Hourly Cost  2418.4710032765515
--- Hour  72 ---
Hourly Cost  2418.4710032765515
--- Hour  73 ---
Hourly Cost  2418.4710032765515
--- Hour  74 ---
Hourly Cost  2418.4710032765515
--- Hour  75 ---
Hourly Cost  2418.4710032765515
--- Hour  76 ---
Hourly Cost  2418.4710032765515
--- Hour  77 ---
Hourly Cost  2418.4710032765515
--- Hour  78 ---
Hourly Cost  2418.4710032765515
--- Hour  79 ---
Hourly Cost  2418.4710032765515
--- Hour  80 ---
Hourly Cost  2418.4710032765515
--- Hour  81 ---
Hourly Cost  2418.4710032765515
--- Hour  82 ---
Hourly Cost  2418.4710032765515
--- Hour  83 ---
Hourly Cost  2418.4710032765515
--- Hour  84 ---
Hourly Cost  2418.4710032765515
--- Hour  85 ---
Hourly Cost  2418.4710032765515
--- Hour  86 ---
Hourly Cost  2418.4710032765515
--- Hour  87 ---
Hourly Cost  2418.4710032765515
--- Hour  88 ---
Hourly Cost  2418.4710032765515
--- Hour  89 ---
Hourly Cost  2418.4710032765515
--- Hour  90 ---
Hourly Cost  2418.4710032765515
--- Hour  91 ---
Hourly Cost  2418.4710032765515
--- Hour  92 ---
Hourly Cost  2418.4710032765515
--- Hour  93 ---
Hourly Cost  2418.4710032765515
--- Hour  94 ---
Hourly Cost  2418.4710032765515
--- Hour  95 ---
Hourly Cost  2418.4710032765515
--- Hour  96 ---
Hourly Cost  2418.4710032765515
--- Hour  97 ---
Hourly Cost  2418.4710032765515
--- Hour  98 ---
Hourly Cost  2418.4710032765515
--- Hour  99 ---
Hourly Cost  2418.4710032765515
--- Hour  100 ---
Hourly Cost  2418.4710032765515
--- Hour  101 ---
Hourly Cost  2418.4710032765515
--- Hour  102 ---
Hourly Cost  2418.4710032765515
--- Hour  103 ---
Hourly Cost  2418.4710032765515
--- Hour  104 ---
Hourly Cost  2418.4710032765515
--- Hour  105 ---
Hourly Cost  2418.4710032765515
--- Hour  106 ---
Hourly Cost  2418.4710032765515
--- Hour  107 ---
Hourly Cost  2418.4710032765515
--- Hour  108 ---
Hourly Cost  2418.4710032765515
--- Hour  109 ---
Hourly Cost  2418.4710032765515
--- Hour  110 ---
Hourly Cost  2418.4710032765515
--- Hour  111 ---
Hourly Cost  2418.4710032765515
--- Hour  112 ---
Hourly Cost  2418.4710032765515
--- Hour  113 ---
Hourly Cost  2418.4710032765515
--- Hour  114 ---
Hourly Cost  2418.4710032765515
--- Hour  115 ---
Hourly Cost  2418.4710032765515
--- Hour  116 ---
Hourly Cost  2418.4710032765515
--- Hour  117 ---
Hourly Cost  2418.4710032765515
--- Hour  118 ---
Hourly Cost  2418.4710032765515
--- Hour  119 ---
Hourly Cost  2418.4710032765515
--- Hour  120 ---
Hourly Cost  2418.4710032765515
--- Hour  121 ---
Hourly Cost  2418.4710032765515
--- Hour  122 ---
Hourly Cost  2418.4710032765515
--- Hour  123 ---
Hourly Cost  2418.4710032765515
--- Hour  124 ---
Hourly Cost  2418.4710032765515
--- Hour  125 ---
Hourly Cost  2418.4710032765515
--- Hour  126 ---
Hourly Cost  2418.4710032765515
--- Hour  127 ---
Hourly Cost  2418.4710032765515
--- Hour  128 ---
Hourly Cost  2418.4710032765515
--- Hour  129 ---
Hourly Cost  2418.4710032765515
--- Hour  130 ---
Hourly Cost  2418.4710032765515
--- Hour  131 ---
Hourly Cost  2418.4710032765515
--- Hour  132 ---
Hourly Cost  2418.4710032765515
--- Hour  133 ---
Hourly Cost  2418.4710032765515
--- Hour  134 ---
Hourly Cost  2418.4710032765515
--- Hour  135 ---
Hourly Cost  2418.4710032765515
--- Hour  136 ---
Hourly Cost  2418.4710032765515
--- Hour  137 ---
Hourly Cost  2418.4710032765515
--- Hour  138 ---
Hourly Cost  2418.4710032765515
--- Hour  139 ---
Hourly Cost  2418.4710032765515
--- Hour  140 ---
Hourly Cost  2418.4710032765515
--- Hour  141 ---
Hourly Cost  2418.4710032765515
--- Hour  142 ---
Hourly Cost  2418.4710032765515
--- Hour  143 ---
Hourly Cost  2418.4710032765515
--- Hour  144 ---
Hourly Cost  2418.4710032765515
--- Hour  145 ---
Hourly Cost  2418.4710032765515
--- Hour  146 ---
Hourly Cost  2418.4710032765515
--- Hour  147 ---
Hourly Cost  2418.4710032765515
--- Hour  148 ---
Hourly Cost  2418.4710032765515
--- Hour  149 ---
Hourly Cost  2418.4710032765515
--- Hour  150 ---
Hourly Cost  2418.4710032765515
--- Hour  151 ---
Hourly Cost  2418.4710032765515
--- Hour  152 ---
Hourly Cost  2418.4710032765515
--- Hour  153 ---
Hourly Cost  2418.4710032765515
--- Hour  154 ---
Hourly Cost  2418.4710032765515
--- Hour  155 ---
Hourly Cost  2418.4710032765515
--- Hour  156 ---
Hourly Cost  2418.4710032765515
--- Hour  157 ---
Hourly Cost  2418.4710032765515
--- Hour  158 ---
Hourly Cost  2418.4710032765515
--- Hour  159 ---
Hourly Cost  2418.4710032765515
---= Keep the equipment =---
Total operating Cost  324985.21754533396
Now that we've established the total cost of ownership, we can script replacing the tractor at a specific amount of workHours like so.
We also run an example of replacing the Fendt every 40 hours over 10 years

Code: Select all

def costOfOwnershipReplace(price, opHoursPerYear, replaceAtOpHour, yearsToRunSim):
    sumCost = 0
    operatingTime = 1
    age = 0
    for hours in range (1, yearsToRunSim*opHoursPerYear):
        #print("--- Hour ", hours, "---")
        if operatingTime >= replaceAtOpHour:
            replaceCost = price - sellValue(price, age, operatingTime*3600)
            #print("Replace cost ", replaceCost, " at age ", age, " and opHours ", operatingTime)
            sumCost = sumCost + replaceCost
            age = 0
            operatingTime = 1
        else:
            hourCost = repairCostOverTime(price, 480, (operatingTime-1)*3600, operatingTime*3600)
            #print("Hourly Cost ", hourCost)
            operatingTime = operatingTime + 1
            sumCost = sumCost + hourCost
            if (operatingTime % opHoursPerYear) == 0:
                age = age + 1
    #print("---= Replace the equipment =---")
    #print("Total operating Cost ", sumCost)
    return sumCost

costOfOwnershipReplace(329000,16,40,10)

Code: Select all

--- Hour  1 ---
Hourly Cost  284.4907877464182
--- Hour  2 ---
Hourly Cost  312.210424689934
--- Hour  3 ---
Hourly Cost  340.77610086327354
--- Hour  4 ---
Hourly Cost  370.16346281333176
--- Hour  5 ---
Hourly Cost  400.3501468940273
--- Hour  6 ---
Hourly Cost  431.3155221572384
--- Hour  7 ---
Hourly Cost  463.0404774908134
--- Hour  8 ---
Hourly Cost  495.5072436679148
--- Hour  9 ---
Hourly Cost  528.6992432725746
--- Hour  10 ---
Hourly Cost  562.6009631254026
--- Hour  11 ---
Hourly Cost  597.1978450489814
--- Hour  12 ---
Hourly Cost  632.4761917158634
--- Hour  13 ---
Hourly Cost  668.423085002493
--- Hour  14 ---
Hourly Cost  705.0263147908387
--- Hour  15 ---
Hourly Cost  742.2743165590208
--- Hour  16 ---
Hourly Cost  780.1561164132092
--- Hour  17 ---
Hourly Cost  818.6612824573699
--- Hour  18 ---
Hourly Cost  857.7798815910962
--- Hour  19 ---
Hourly Cost  897.5024409804498
--- Hour  20 ---
Hourly Cost  937.8199135713081
--- Hour  21 ---
Hourly Cost  978.7236471156625
--- Hour  22 ---
Hourly Cost  1020.2053562637218
--- Hour  23 ---
Hourly Cost  1062.2570973423353
--- Hour  24 ---
Hourly Cost  1104.8712454961305
--- Hour  25 ---
Hourly Cost  1148.0404739141677
--- Hour  26 ---
Hourly Cost  1191.7577349036646
--- Hour  27 ---
Hourly Cost  1236.0162426048291
--- Hour  28 ---
Hourly Cost  1280.8094571682661
--- Hour  29 ---
Hourly Cost  1326.131070239554
--- Hour  30 ---
Hourly Cost  1371.9749916153376
--- Hour  31 ---
Hourly Cost  1418.3353369521449
--- Hour  32 ---
Hourly Cost  1465.2064164233996
--- Hour  33 ---
Hourly Cost  1512.5827242326895
--- Hour  34 ---
Hourly Cost  1560.4589289019073
--- Hour  35 ---
Hourly Cost  1608.8298642621169
--- Hour  36 ---
Hourly Cost  1657.6905210831587
--- Hour  37 ---
Hourly Cost  1707.036039284886
--- Hour  38 ---
Hourly Cost  1756.8617006790696
--- Hour  39 ---
Hourly Cost  1807.1629221963822
--- Hour  40 ---
Replace cost  58781.333333333314  at age  2  and opHours  40
--- Hour  41 ---
Hourly Cost  284.4907877464182
--- Hour  42 ---
Hourly Cost  312.210424689934
--- Hour  43 ---
Hourly Cost  340.77610086327354
--- Hour  44 ---
Hourly Cost  370.16346281333176
--- Hour  45 ---
Hourly Cost  400.3501468940273
--- Hour  46 ---
Hourly Cost  431.3155221572384
--- Hour  47 ---
Hourly Cost  463.0404774908134
--- Hour  48 ---
Hourly Cost  495.5072436679148
--- Hour  49 ---
Hourly Cost  528.6992432725746
--- Hour  50 ---
Hourly Cost  562.6009631254026
--- Hour  51 ---
Hourly Cost  597.1978450489814
--- Hour  52 ---
Hourly Cost  632.4761917158634
--- Hour  53 ---
Hourly Cost  668.423085002493
--- Hour  54 ---
Hourly Cost  705.0263147908387
--- Hour  55 ---
Hourly Cost  742.2743165590208
--- Hour  56 ---
Hourly Cost  780.1561164132092
--- Hour  57 ---
Hourly Cost  818.6612824573699
--- Hour  58 ---
Hourly Cost  857.7798815910962
--- Hour  59 ---
Hourly Cost  897.5024409804498
--- Hour  60 ---
Hourly Cost  937.8199135713081
--- Hour  61 ---
Hourly Cost  978.7236471156625
--- Hour  62 ---
Hourly Cost  1020.2053562637218
--- Hour  63 ---
Hourly Cost  1062.2570973423353
--- Hour  64 ---
Hourly Cost  1104.8712454961305
--- Hour  65 ---
Hourly Cost  1148.0404739141677
--- Hour  66 ---
Hourly Cost  1191.7577349036646
--- Hour  67 ---
Hourly Cost  1236.0162426048291
--- Hour  68 ---
Hourly Cost  1280.8094571682661
--- Hour  69 ---
Hourly Cost  1326.131070239554
--- Hour  70 ---
Hourly Cost  1371.9749916153376
--- Hour  71 ---
Hourly Cost  1418.3353369521449
--- Hour  72 ---
Hourly Cost  1465.2064164233996
--- Hour  73 ---
Hourly Cost  1512.5827242326895
--- Hour  74 ---
Hourly Cost  1560.4589289019073
--- Hour  75 ---
Hourly Cost  1608.8298642621169
--- Hour  76 ---
Hourly Cost  1657.6905210831587
--- Hour  77 ---
Hourly Cost  1707.036039284886
--- Hour  78 ---
Hourly Cost  1756.8617006790696
--- Hour  79 ---
Hourly Cost  1807.1629221963822
--- Hour  80 ---
Replace cost  58781.333333333314  at age  2  and opHours  40
--- Hour  81 ---
Hourly Cost  284.4907877464182
--- Hour  82 ---
Hourly Cost  312.210424689934
--- Hour  83 ---
Hourly Cost  340.77610086327354
--- Hour  84 ---
Hourly Cost  370.16346281333176
--- Hour  85 ---
Hourly Cost  400.3501468940273
--- Hour  86 ---
Hourly Cost  431.3155221572384
--- Hour  87 ---
Hourly Cost  463.0404774908134
--- Hour  88 ---
Hourly Cost  495.5072436679148
--- Hour  89 ---
Hourly Cost  528.6992432725746
--- Hour  90 ---
Hourly Cost  562.6009631254026
--- Hour  91 ---
Hourly Cost  597.1978450489814
--- Hour  92 ---
Hourly Cost  632.4761917158634
--- Hour  93 ---
Hourly Cost  668.423085002493
--- Hour  94 ---
Hourly Cost  705.0263147908387
--- Hour  95 ---
Hourly Cost  742.2743165590208
--- Hour  96 ---
Hourly Cost  780.1561164132092
--- Hour  97 ---
Hourly Cost  818.6612824573699
--- Hour  98 ---
Hourly Cost  857.7798815910962
--- Hour  99 ---
Hourly Cost  897.5024409804498
--- Hour  100 ---
Hourly Cost  937.8199135713081
--- Hour  101 ---
Hourly Cost  978.7236471156625
--- Hour  102 ---
Hourly Cost  1020.2053562637218
--- Hour  103 ---
Hourly Cost  1062.2570973423353
--- Hour  104 ---
Hourly Cost  1104.8712454961305
--- Hour  105 ---
Hourly Cost  1148.0404739141677
--- Hour  106 ---
Hourly Cost  1191.7577349036646
--- Hour  107 ---
Hourly Cost  1236.0162426048291
--- Hour  108 ---
Hourly Cost  1280.8094571682661
--- Hour  109 ---
Hourly Cost  1326.131070239554
--- Hour  110 ---
Hourly Cost  1371.9749916153376
--- Hour  111 ---
Hourly Cost  1418.3353369521449
--- Hour  112 ---
Hourly Cost  1465.2064164233996
--- Hour  113 ---
Hourly Cost  1512.5827242326895
--- Hour  114 ---
Hourly Cost  1560.4589289019073
--- Hour  115 ---
Hourly Cost  1608.8298642621169
--- Hour  116 ---
Hourly Cost  1657.6905210831587
--- Hour  117 ---
Hourly Cost  1707.036039284886
--- Hour  118 ---
Hourly Cost  1756.8617006790696
--- Hour  119 ---
Hourly Cost  1807.1629221963822
--- Hour  120 ---
Replace cost  58781.333333333314  at age  2  and opHours  40
--- Hour  121 ---
Hourly Cost  284.4907877464182
--- Hour  122 ---
Hourly Cost  312.210424689934
--- Hour  123 ---
Hourly Cost  340.77610086327354
--- Hour  124 ---
Hourly Cost  370.16346281333176
--- Hour  125 ---
Hourly Cost  400.3501468940273
--- Hour  126 ---
Hourly Cost  431.3155221572384
--- Hour  127 ---
Hourly Cost  463.0404774908134
--- Hour  128 ---
Hourly Cost  495.5072436679148
--- Hour  129 ---
Hourly Cost  528.6992432725746
--- Hour  130 ---
Hourly Cost  562.6009631254026
--- Hour  131 ---
Hourly Cost  597.1978450489814
--- Hour  132 ---
Hourly Cost  632.4761917158634
--- Hour  133 ---
Hourly Cost  668.423085002493
--- Hour  134 ---
Hourly Cost  705.0263147908387
--- Hour  135 ---
Hourly Cost  742.2743165590208
--- Hour  136 ---
Hourly Cost  780.1561164132092
--- Hour  137 ---
Hourly Cost  818.6612824573699
--- Hour  138 ---
Hourly Cost  857.7798815910962
--- Hour  139 ---
Hourly Cost  897.5024409804498
--- Hour  140 ---
Hourly Cost  937.8199135713081
--- Hour  141 ---
Hourly Cost  978.7236471156625
--- Hour  142 ---
Hourly Cost  1020.2053562637218
--- Hour  143 ---
Hourly Cost  1062.2570973423353
--- Hour  144 ---
Hourly Cost  1104.8712454961305
--- Hour  145 ---
Hourly Cost  1148.0404739141677
--- Hour  146 ---
Hourly Cost  1191.7577349036646
--- Hour  147 ---
Hourly Cost  1236.0162426048291
--- Hour  148 ---
Hourly Cost  1280.8094571682661
--- Hour  149 ---
Hourly Cost  1326.131070239554
--- Hour  150 ---
Hourly Cost  1371.9749916153376
--- Hour  151 ---
Hourly Cost  1418.3353369521449
--- Hour  152 ---
Hourly Cost  1465.2064164233996
--- Hour  153 ---
Hourly Cost  1512.5827242326895
--- Hour  154 ---
Hourly Cost  1560.4589289019073
--- Hour  155 ---
Hourly Cost  1608.8298642621169
--- Hour  156 ---
Hourly Cost  1657.6905210831587
--- Hour  157 ---
Hourly Cost  1707.036039284886
--- Hour  158 ---
Hourly Cost  1756.8617006790696
--- Hour  159 ---
Hourly Cost  1807.1629221963822
---= Replace the equipment =---
Total operating Cost  328509.69412612385
As we can see, the replace cost is offset by the lower maintenance, up to the point that it makes sense to replace the tractor 3 times, albeit at a small loss.

Now we can combine the two scripts but first calculating the keep forever cost and search for the soonest time we can replace and have economic benefit.

Code: Select all

minCostToReplace = price*10
    minCostToReplaceHours = 0 
    costToKeep = costOfOwnershipKeep(price, opHoursPerYear, yearsToRunSim)
    for replaceHours in range (1, yearsToRunSim*opHoursPerYear):
        costToReplace = costOfOwnershipReplace(price, opHoursPerYear, replaceHours, yearsToRunSim)
        if costToReplace < costToKeep:
            print("Replace at ",  replaceHours, " op Hours")
            print("Operating cost to keep ", costToKeep)
            print("Operating cost to replace ", costToReplace)
            return
        else:
            if costToReplace < minCostToReplace:
                minCostToReplace = costToReplace
                minCostToReplaceHours = replaceHours
    print("Replacing not profitable")
    print("Operating cost to keep ", costToKeep)
    print("Min Operating cost to replace ", minCostToReplace, " each ", minCostToReplaceHours, " hours")

whenToReplace(329000,16,10)

Code: Select all

Replacing not profitable
Operating cost to keep  324985.21754533396
Min Operating cost to replace  328509.69412612385  each  40  hours
Last edited by george.earlslight on Sat Jan 22, 2022 2:36 pm, edited 2 times in total.
george.earlslight
Posts: 784
Joined: Tue Nov 20, 2018 11:45 am
Location: Europe

Re: Cost of owning vehicles/equipment - Optimal time to replace - Detailed cost analysis

Post by george.earlslight »

Part 5. Summary

As it seems, your first reply to my question was correct but I had a good time trying to validate it.
Keeping equipment forever, but repairing as soon as possible is the most economic decision game wise.

And this is where Giants can do better.
First and foremost, adding damage while sitting on a tractor without even the engine on is just plain wrong.
Moreover, adding the same amount of damage, only dependent on work hours, ignoring the type and amount of effort, is also wrong.
Encouraging the player to repair their equipment so often is not realistic or fun.

With the introduction of seasonal cycles, it would make sense to allow the farm economy flow naturally.
Run maintenance every X hours of work or once a year. Do you need to run maintenance many times per year?
That would be a sign that you need more or bigger equipment.

Personally, I'd be interested to a maintenance themed DLC.
Maintenance is a very important part of any farm and as such I think the game would benefit out of it.
Remove the damage percentage, it doesn't translate to anything in real life.
Replace it with operating hours since last service.
Add effects relevant to the equipment, if it's not properly serviced.
Ruptured tyre, faulty hydraulics, turbo pipe disconnected, not starting for tractors.
Row not pushing seeds, hydraulics not lowering on seeders/planters.
Row tine fallen off on cultivator.
This would create an interesting system, where maintenance isn't just a function of time and cost on the player's mind.

Bellow the link to the calculation sheets and the full python script.

Code: Select all

https://docs.google.com/spreadsheets/d/1KyPVa1dgnLlYSG7xfbVcrGCKHRhVL5mz8P0u7xKiv_Q/edit?usp=sharing

Code: Select all

import math

def damageRate(wearDuration, operatingTime):
    if operatingTime > (3600*50):
        operatingTime = 3600*50
    return (0.35 / (wearDuration/60)) + (0.00289*(operatingTime/3600))

def damageDone(wearDuration, operatingTimeStart, operatingTimeEnd):
    totDamage = 0
    simTime = operatingTimeStart   
    while simTime < operatingTimeEnd:
        damage = damageRate(wearDuration, simTime) * (1/3600)
        totDamage = totDamage + damage
        simTime = simTime + 1
    return totDamage
    
def repairCost(price, damage):
    return (0.09 * pow(damage, 1.5) * price)
    
def repairCostOverTime(price, wearDuration, operatingTimeStart, operatingTimeEnd):
    return (repairCost(price,damageDone(wearDuration, operatingTimeStart, operatingTimeEnd)))
    
def sellValue(price, age, operatingTime):
    usedPrice = price * 0.88
    
    if age > 7:
        ageDevaluation = 1.25-(0.125*math.log(age))
    else:
        ageDevaluation = 1
    
    useDevaluation = (1-(5/3000*operatingTime/3600))
    
    return (usedPrice*ageDevaluation*useDevaluation)

#assumes repair every hour
def costOfOwnershipKeep(price, opHoursPerYear, yearsToRunSim):
    sumCost = 0
    for hours in range (1, yearsToRunSim*opHoursPerYear):
        #print("--- Hour ", hours, "---")
        hourCost = repairCostOverTime(price, 480, (hours-1)*3600, hours*3600)
        #print("Hourly Cost ", hourCost)
        sumCost = sumCost + hourCost
    #print("---= Keep the equipment =---")
    #print("Total operating Cost ", sumCost)
    return sumCost
       
def costOfOwnershipReplace(price, opHoursPerYear, replaceAtOpHour, yearsToRunSim):
    sumCost = 0
    operatingTime = 1
    age = 0
    for hours in range (1, yearsToRunSim*opHoursPerYear):
        #print("--- Hour ", hours, "---")
        if operatingTime >= replaceAtOpHour:
            replaceCost = price - sellValue(price, age, operatingTime*3600)
            #print("Replace cost ", replaceCost, " at age ", age, " and opHours ", operatingTime)
            sumCost = sumCost + replaceCost
            age = 0
            operatingTime = 1
        else:
            hourCost = repairCostOverTime(price, 480, (operatingTime-1)*3600, operatingTime*3600)
            #print("Hourly Cost ", hourCost)
            operatingTime = operatingTime + 1
            sumCost = sumCost + hourCost
            if (operatingTime % opHoursPerYear) == 0:
                age = age + 1
    #print("---= Replace the equipment =---")
    #print("Total operating Cost ", sumCost)
    return sumCost
    
def whenToReplace(price, opHoursPerYear, yearsToRunSim):
    minCostToReplace = price*10
    minCostToReplaceHours = 0 
    costToKeep = costOfOwnershipKeep(price, opHoursPerYear, yearsToRunSim)
    for replaceHours in range (1, yearsToRunSim*opHoursPerYear):
        costToReplace = costOfOwnershipReplace(price, opHoursPerYear, replaceHours, yearsToRunSim)
        if costToReplace < costToKeep:
            print("Replace at ",  replaceHours, " op Hours")
            print("Operating cost to keep ", costToKeep)
            print("Operating cost to replace ", costToReplace)
            return
        else:
            if costToReplace < minCostToReplace:
                minCostToReplace = costToReplace
                minCostToReplaceHours = replaceHours
    print("Replacing not profitable")
    print("Operating cost to keep ", costToKeep)
    print("Min Operating cost to replace ", minCostToReplace, " each ", minCostToReplaceHours, " hours")

whenToReplace(329000,4,10)

Last edited by george.earlslight on Sat Jan 22, 2022 2:36 pm, edited 1 time in total.
humbe
Posts: 1415
Joined: Sat Jan 18, 2020 9:33 pm

Re: Cost of owning vehicles/equipment - Optimal time to replace - Detailed cost analysis

Post by humbe »

Great finds 🙂 And thanks for adding your finds. Will have to look at details once I get back home..
paul_c
Posts: 414
Joined: Thu Nov 25, 2021 4:13 pm

Re: Cost of owning vehicles/equipment - Optimal time to replace - Detailed cost analysis

Post by paul_c »

Brilliant! So......ummm.......50 hours?
humbe
Posts: 1415
Joined: Sat Jan 18, 2020 9:33 pm

Re: Cost of owning vehicles/equipment - Optimal time to replace - Detailed cost analysis

Post by humbe »

paul_c wrote: Sat Jan 22, 2022 2:49 pm Brilliant! So......ummm.......50 hours?
Hehe.. Feel free to replace your gear after 50 hours but sounds to me the conclusion still stands. Cheaper the longer you keep the gear so you have to decide when the loss of buying new is small enough to work for you or you are just tired of your old stuff
paul_c
Posts: 414
Joined: Thu Nov 25, 2021 4:13 pm

Re: Cost of owning vehicles/equipment - Optimal time to replace - Detailed cost analysis

Post by paul_c »

I will read and digest it but I don't think there is a clear answer - sure, you can carry on using the same equipment and if you replaced like-for-like new, then theoretically there is a point "x" hours its more cost effective to replace (which will also be a complex function of other things, such as work time/year and how often you can get it in for repair). But I like my idea of doing a half-step upgrade each time. Additionally, replacing a bit sooner gives the advantage of tweaks on the performance/power of a tractor, for example if you like a cab with a better view, or 4WS, or whatever.

The other option is to buy a tractor merely for those jobs where speed/fuel economy isn't so important - for example, transport, loading, ploughing, cultivating - and NEVER repair it, ever. Just let it degrade then just keep using it until its thousands of hours old. (Its a shame my most recent boss subscribed to this idea...)

My hunch is that repairs little and often are a good strategy until ~40 hours, then keep using it for 5-10 more hours, then get a replacement (half a step up) at that point. Then you build a useful and varied fleet, rather than simply like-for-like. Also, I will never sell a tractor, unless it becomes genuinely unused due to replacement(s) and work style.
george.earlslight
Posts: 784
Joined: Tue Nov 20, 2018 11:45 am
Location: Europe

Re: Cost of owning vehicles/equipment - Optimal time to replace - Detailed cost analysis

Post by george.earlslight »

I'm guessing 40-50h would match most play styles.
You can always phase out older equipment and use them in odd jobs, while using newer/bigger to keep maintenance and work hours low.
That's the natural evolution of most farms.

Honestly I'm more interested in a maintenance revamp from Giants after finding out how the current system works.
humbe
Posts: 1415
Joined: Sat Jan 18, 2020 9:33 pm

Re: Cost of owning vehicles/equipment - Optimal time to replace - Detailed cost analysis

Post by humbe »

As long as theres no point at where Im losing money by still using something, Ill probably decide on when to buy new based on when I have money to spare and when I need more power as I tire of low working width..
Post Reply