Probability of an event occurring when represented as whole numbers in percentage form

Currently, I'm developing a unique job system within a Discord bot that allows users to mine various types of ores. The probability of receiving specific ores is based on the user's mining skill level, which is stored in a database and can vary accordingly. For example, at Skill Level 1, the chances are as follows:

let coal_chance = 80
let copper_chance = 15
let iron_chance = 5
let gold_chance = 0
let diamond_chance = 0
let emerald_chance = 0

Conversely, at Skill Level 2, the distribution changes:

let coal_chance = 50
let copper_chance = 35
let iron_chance = 10
let gold_chance = 5
let diamond_chance = 0
let emerald_chance = 0

This pattern continues for higher skill levels. However, my current dilemma lies in creating a dynamic chance system based on these percentages.

I initially attempted to implement a solution using Math.Random() alongside a series of if statements. Unfortunately, this approach proved inefficient since it required separate conditionals for each skill level. Furthermore, any adjustments made to the ore probabilities within the database would necessitate corresponding alterations to the codebase.

Answer №1

After seeing a suggestion from @sudheeshix, I devised this makeshift solution:

const cumulativeChances = [ 
  {c: 100, i: "coal"},
  {c: 50, i: "copper"},
  {c: 15, i: "iron"},
  {c: 5, i: "gold"},
  {c: 0, i: "emerald"},
  {c: 0, i: "diamond"}
]
const mineOre = () => {
  let rng = Math.random() * 100
  let won = 'coal'
  for (item of cumulativeChances) {
    if (item.c < rng) break
    won = item.i
  }
  return won
}

// Testing if it works as intended
const calculatedChances = {
  coal: 0,
  copper: 0,
  iron: 0,
  gold: 0,
  emerald: 0,
  diamond: 0
}
let tries = i = 10000;
while(i--) {
  let won = mineOre()
  calculatedChances[won] += (1 / tries * 100)
}
console.log(calculatedChances)

While there may be areas for enhancement, this concept offers a starting point. Happy coding :)

Answer №2

Let's explore a different approach:

First, transform your resource values into an array:

resources = ["silver", "bronze", "steel", "titanium", "platinum", "sapphire"];
chances = [70, 10, 15, 5, 0, 0];

Next, calculate cumulative sums of the percentages, following the method described in this response.

const cumulativeSum = (sum => value => sum += value/100)(0);
cum_chances = chances.map(cumulativeSum);

The division by 100 is necessary to obtain float values since Math.random() generates numbers between 0 and 1. Using the chances values above, cum_chances would be [0.7, 0.8, 0.95, 1, 1, 1].

Now, generate a random probability.

random_prob = Math.random();

Then, determine the index of the first element in the array where random_prob fits using the guidance provided in this suggestion.

idx = cum_chances.findIndex(function (el) {
    return el >= random_prob;
});
resource_found = resources[idx];

For instance, if random_prob equals 0.85, this process will yield an index of 2, resulting in resources[idx] returning "steel".

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

An issue has been detected in the constants.json file located in the constants-browserify

I organized my folders into client-side and server-side categories, but I failed to work from a parent folder perspective. Now, as I attempt to deploy to Heroku, I realize that I need one main folder for the deployment process. To address this issue, I dec ...

The functionality of verifying the type of an item in a list using Typescript is not functioning

In my TypeScript code, I am working with a type called NameValue and another one called MixedStuff. type NameValue = { name: string; value: string }; type MixedStuff = NameValue | string; function stripTwoChars(stuffs: MixedStuff[]): string { let st ...

Receiving an error stating "module not found" when attempting to retrieve the NextAuth session using EmailProvider in getServerSideProps

Trying to access the NextAuth session from a server-side call within getServerSideProps, using an EmailProvider with NextAuth. Referring to an example in NextAuth's documentation, I'm attempting to retrieve the session from getServerSideProps. T ...

My React app experienced a severe crash when trying to render an animation in L

Currently, I am working on a React application that was set up using Vite. I recently incorporated an animation using Lottie, and although I was successful in implementing it, I encountered a problem when navigating between different pages of my applicati ...

Executing a function while adjusting a range slider

Having an <input type="range"> element on my website presents a particular challenge. To handle changes in this element, I am using the following function: $("#selector").bind("change", function() { //perform desire ...

What are the steps for running app.js deployed on a remote server using the local bash terminal?

After launching my web application on GoDaddy, which is built in Node.js, I have encountered a dilemma. In order to run app.js, I currently rely on my computer's bash command prompt. However, this poses an issue - if I were to shut down my laptop, the ...

The backtick is not functioning correctly when trying to append the result in the Internet Explorer browser

I am using the .html method to append HTML content to a specific div ID within my file. <html> <head> Title <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> </head> <body> ...

What measures do websites such as yelp and urbandictionary implement to avoid multiple votes from unregistered users?

It is interesting to note that on urbandictionary, you do not need to be logged in to upvote a definition. For example, if you visit and upvote the first word, it will record your vote. Even if you open an incognito window and try to upvote again, or use ...

How can one specify a type in Typescript with a precise number of properties with unspecified names?

Imagine I have a variable with a name and a value, both of which I need for a specific task such as logging. This can be achieved in the following way: const some_variable = "abcdef" const another_variable = 12345 const log1 = (name: string, value: any) ...

Tips for organizing JSON object data and displaying it appropriately on an HTML page

This code utilizes ajax: $("form").on("submit", function () { var data = { "action": "test" }; data = $(this).serialize() + "&" + $.param(data); $.ajax({ type: "POST", dataType: "json", url: "ajax2.php" ...

Having trouble with jQuery.cookie saving my JSON data

Being new to jQuery and JSON, I find this situation quite frustrating as it seems pretty straightforward but still doesn't work for me. My ASP.NET MVC website is using AJAX (via jQuery) to load data. Everything works fine until this point. I'm ...

Transforming Google Maps from using jQuery to AngularJS

If I have a Jquery google map with find address and routing system, my goal is to convert it to an angular google map with more options. The current Jquery google map code looks like this: var directionsDisplay = new google.maps.DirectionsRenderer({ d ...

Managing DOM elements within a Vue 3 template using Typescript

As I delve into the world of Vue 3 as a beginner, I encountered a challenge when it came to managing the DOM within Vue 3 templates. Let's take a look at the source code. MainContainer.vue <template> <div class="main-container" r ...

Tips for keeping notification icons in the upper right corner of the box?

I am facing an issue with absolute positioning where the notification icons I've positioned to the top-right corner of a box are moving away when the screen size changes. Desired appearance of the image Actual appearance when screen size is adjusted ...

Sending a Thunk to the store using Typescript

Within my primary store.ts file, the following code is present: const store = createStore( rootReducer, composeWithDevTools(applyMiddleware(thunk)) ); store.dispatch(fetchUser()); Upon initial rendering, an action is dispatched to fetchUser in ord ...

Tips for adjusting the width of a Facebook embedded video within its container using ReactPlayer

Has anyone encountered issues with adding an embedded video to a NextJS app using ReactPlayer and Facebook videos? It seems that Facebook does not support the width="100%" attribute, as it always snaps back to 500px. Interestingly, this works wel ...

Comparing two Objects in JavaScript results in automatic updates for the second Object when changes are made to the first

Can someone please assist me with a hash map issue I'm encountering in my for loop? When resetting the second object, it unintentionally alters the Map values of the previous Key in the Hash Map. Any guidance on how to prevent this behavior would be g ...

Apollo-Server presents errors in a polished manner

It seems like the question explains itself adequately. I am currently using 'apollo-server-core' version 3.6.5 Desired Errors: { "errors": [ { "message": "Syntax Error: Unexpected < ...

Navigate the array and divide the elements into separate values

For a project I need to upload files, wherein the data is organized within an object like [5.76516834507, 50.8474898368], [5.76115833641, 50.8453698247]. The task here is to extract and store the first value as latitude: 5.76516834507 and the second value ...

Iterate through JSON objects

Having an issue with looping through JSON using jQuery AJAX. Despite receiving the JSON data from PHP and converting it to a string, I'm unable to loop through it properly in JavaScript. In my for loop, I need to access $htmlvalue[i] to parse the data ...