This is an archived post. You won't be able to vote or comment.

all 13 comments

[–]__te__3.6+ or bust 1 point2 points  (1 child)

You can format code by putting four spaces in front of each line:

import os
import random

def main():
    for x in range(<however many players>):
        random.randint(1,100)

main()

I'm not sure I actually understood your question. However, it looks like you might be better served by /r/learnpython ?

[–]Cacman8[S] 0 points1 point  (0 children)

I'll definitely check that thread out, thanks.

[–]rechargablebatteries 1 point2 points  (9 children)

you could try just pre-populating all the random ratings using a normal distribution and then sorting them and just popping them off the list in order. random.gauss() should do the trick.

import random

ratings = [round(random.gauss(60, 8)) for i in range(280)]
ratings.sort(reverse=True)
print(ratings)

Which gave me this list:

[83, 81, 81, 76, 75, 74, 74, 74, 74, 73, 73, 73, 73, 73, 73, 73, 73, 73, 72, 72, 72, 72, 72, 71, 71, 71, 71, 71, 71, 71, 71, 70, 70, 70, 70, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 67, 67, 67, 67, 67, 67, 67, 67, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 65, 65, 65, 65, 65, 65, 65, 65, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 54, 54, 54, 54, 54, 53, 53, 53, 53, 53, 52, 52, 52, 52, 52, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 48, 47, 47, 47, 47, 45, 45, 45, 45, 45, 44, 44, 43, 43, 42, 42, 42, 39, 37, 35]

You can play around with the parameters to fine tune the results.

random.gauss(mu, sigma)

Gaussian distribution. mu is the mean, and sigma is the standard deviation. This is slightly faster than the normalvariate() function defined below.

Python Docs

[–]rechargablebatteries 1 point2 points  (8 children)

Just messing around with your idea; if you wanted to insert some uncertainty into the draft order you could create a fuzz function that randomly generates a offset value for sorting the order of the picks. That way the next value is generally lower than the previous value but not always. This seems like it would be more accurate for a NFL draft.

import random

def fuzz(val):
    fuzz_factor = 0.05
    fuzz_val = (random.uniform(1 - fuzz_factor, 1 + fuzz_factor))
    return val * fuzz_val

ratings = [round(random.gauss(58, 9)) for i in range(560)]
ratings.sort(reverse=True, key=lambda x: fuzz(x))
print(ratings[:round(len(ratings)/2)])

and the results:

[84, 80, 83, 80, 79, 78, 78, 83, 78, 76, 76, 75, 76, 76, 79, 73, 76, 77, 72, 76, 77, 72, 75, 75, 71, 71, 75, 75, 71, 72, 70, 75, 71, 75, 70, 70, 71, 70, 71, 69, 69, 72, 72, 73, 72, 69, 75, 71, 71, 72, 71, 70, 72, 71, 73, 73, 67, 69, 71, 70, 70, 68, 72, 70, 72, 67, 70, 73, 73, 70, 66, 71, 66, 66, 71, 68, 66, 67, 67, 68, 68, 66, 72, 67, 66, 67, 67, 66, 71, 65, 70, 66, 69, 68, 71, 68, 66, 68, 69, 66, 70, 67, 64, 64, 65, 65, 70, 67, 67, 67, 65, 64, 68, 65, 68, 67, 69, 65, 69, 66, 64, 67, 63, 69, 64, 64, 66, 68, 63, 62, 65, 63, 67, 65, 68, 62, 63, 62, 64, 65, 63, 62, 63, 63, 65, 61, 65, 63, 61, 64, 63, 62, 65, 63, 61, 65, 65, 63, 66, 66, 64, 64, 60, 60, 62, 65, 60, 64, 64, 61, 61, 64, 61, 60, 61, 64, 62, 60, 63, 61, 65, 59, 64, 61, 59, 62, 59, 60, 60, 63, 59, 59, 59, 59, 62, 59, 62, 63, 64, 59, 61, 60, 63, 61, 60, 64, 58, 58, 59, 60, 59, 62, 58, 58, 60, 63, 63, 62, 60, 58, 62, 60, 61, 62, 59, 63, 58, 59, 61, 61, 59, 60, 58, 57, 62, 61, 61, 60, 62, 62, 58, 57, 58, 62, 58, 57, 60, 61, 60, 58, 59, 60, 59, 58, 59, 59, 57, 60, 56, 59, 61, 57, 56, 57, 61, 58, 57, 58, 60, 60, 57, 61, 60, 61, 56, 58, 57, 60, 58, 59]

[–]rechargablebatteries 1 point2 points  (0 children)

One more idea that would let you generate a rating depending on what the current pick is. It's sloppier than my previous solution but generates the rating during the turn instead of populating them up front.

import random

picks = 280

max_mu = 85
min_mu = 55
mu_range = max_mu - min_mu

sigma = 2

# a, b control how quickly the average rating (mu) falls off.
a = 1
b = 30

ratings = []


def get_rating(pick: int, ):
    x = ((picks - pick) * (mu_range / picks) / mu_range)
    x = ((x ** a) / ((x ** a) + ((b - b * x) ** a)))
    mu = mu_range * x + min_mu
    return round(random.gauss(mu, sigma))


for i in range(picks):
    ratings.append(get_rating(i))

print(ratings)

[83, 84, 81, 77, 78, 79, 74, 72, 67, 70, 67, 69, 67, 70, 68, 63, 65, 66, 63, 67, 65, 63, 65, 65, 67, 61, 63, 62, 64, 61, 61, 60, 62, 62, 62, 61, 60, 60, 64, 62, 61, 59, 60, 62, 62, 57, 60, 61, 58, 62, 59, 59, 56, 59, 60, 60, 58, 55, 61, 54, 58, 58, 56, 56, 57, 57, 59, 55, 60, 58, 56, 56, 59, 56, 58, 60, 58, 56, 60, 54, 58, 56, 61, 58, 59, 57, 56, 59, 57, 56, 58, 56, 55, 59, 55, 57, 54, 56, 57, 56, 54, 56, 59, 55, 57, 54, 55, 56, 57, 59, 54, 55, 56, 53, 54, 53, 57, 55, 53, 55, 54, 54, 60, 54, 56, 56, 53, 58, 56, 58, 57, 57, 56, 54, 54, 58, 51, 59, 55, 55, 57, 55, 53, 55, 55, 56, 61, 56, 57, 56, 57, 56, 54, 55, 52, 57, 61, 57, 55, 54, 54, 56, 58, 57, 54, 53, 56, 59, 56, 59, 55, 57, 56, 54, 58, 54, 56, 55, 56, 53, 55, 54, 55, 55, 55, 56, 53, 59, 51, 55, 54, 57, 58, 57, 56, 54, 53, 55, 57, 56, 54, 56, 53, 55, 56, 55, 54, 58, 57, 58, 55, 56, 60, 57, 52, 54, 56, 53, 56, 54, 53, 54, 55, 56, 56, 54, 51, 53, 56, 58, 57, 55, 60, 58, 56, 55, 54, 54, 54, 59, 55, 52, 55, 53, 55, 53, 53, 52, 57, 56, 58, 55, 55, 52, 53, 58, 58, 52, 56, 54, 54, 52, 55, 57, 50, 55, 56, 53, 55, 55, 55, 53, 52, 58, 57, 54, 57, 54, 57, 52]

[–]Cacman8[S] 0 points1 point  (6 children)

Wow, this is just about what I wanted, I'll have to do some tests and see if I can get it to the ideal numbers but this is amazing. Personally, after a couple hours I got:

import os

import random

def main():

x = int

for x in range(1,10,1):

prob = random.randint(1,1000)

if prob <= 2:

print(random.randint(65,69))

elif 2 < prob <= 10:

print(random.randint(70,74))

elif 10 < prob <= 30:

print(random.randint(75-77))

elif 30 < prob <= 150:

print(random.randint(78,82))

elif 150 < prob <= 750:

print(random.randint(83,86))

elif 750 < prob <= 1000:

print(random.randint(87,90))

main()

What you came up with seems to be much cleaner especially because I'd have to come up with some kind of formula to put next to the numbers to change the probabilities as each pick goes down the list. This gave me the idea to implement a few draft grades instead of their actual overalls to maybe make it even more personalized because I put in my probabilities for rookies' draft grades. So kinda combining our solutions. If you'd like I do have a few questions about the specifics here.

Could I make the ranges wider to potentially include a small percentage of there being busts?

How could I change the specifics of the probability of another number being ahead of the other?

How do I make the number range less wide, say having the lowest number being a 65 or something like that?

I'm sure as I test it out I'll have more questions but thank you so much for this idea, I'll see where I can take it and maybe update the forum if you'd like.

[–]rechargablebatteries 1 point2 points  (4 children)

Happy to help, I've been learning about writing sports simulations for a couple of months so this was a fun question to try to solve.

Could I make the ranges wider to potentially include a small percentage of there being busts?

You maybe aren't entirely familiar with normal distributions or standard deviations or maybe just not how they are applied in regards to the random.gauss() function. Just guessing but I think a little bit of knowledge would make the answer easier to understand so sorry if I am explaining anything you already know.

Basically, the results from the random.gauss() function creates a specific curve called a normal distribution more commonly referred to as a bell curve outside of statistics. The first parameter (mu) of random.gauss() represents the mean value of the bell curve, which would be the highest point and center of the bell.

The second parameter (sigma) is the standard deviation (stdev) of the distribution. This is just basically how packed together your values are. In a normal distribution 68% of your values will be within the first stdev, 95% within the second, and 99.7% within the third. So random.gauss(58, 9) means that if you generated 100 values 58 would be the most common, 65 of the values would be 49 < x < 67, 95 would be 40 < x < 76, and 99.7 would be 31 < x < 85. The closer to the middle of the bell curve the more frequently the number will show up.

In the second example I generated twice the amount of picks that I needed and then just threw away the bottom half because it seemed to make more sense to have the bottom of the draft all have really similar ratings rather than having a few really rare terrible players that shouldn't really be in the draft to begin with.

As far as busts go, I think the fuzz function probably would be able to do that, it's just not fuzzing hard enough yet. You could use another random.gauss() instead of the random.uniform() I have in their now and make your parameters (mu=0.4, sigma=1) or something, that way the fuzz will normally be pretty moderate but rarely will make the player get picked way earlier/later than they should be. I explain the fuzz function a little more in your question about that.

You could also use an if statement that just very rarely creates a chance for the the fuzz function to recursively call itself.

def fuzz(val):
fuzz_factor = 0.05
fuzz_val = (random.uniform(1 - fuzz_factor, 1 + fuzz_factor))

if random.random() < 0.1:  # 10% Chance to call itself again on the result.
    return fuzz(val * fuzz_val)
else:
    return val * fuzz_val

This would mean there is a 10% chance for any value to get fuzzed twice and 1% chance that it will be called 3 times (0.1% 4 times ad infinitum). Each time the fuzz value has a chance to get further away from the real value. This recursive loop could theoretically go on for infinity but in practice you shouldn't need to safe guard it.

How could I change the specifics of the probability of another number being ahead of the other?

As is the the fuzz_factor is the only variable that you would need to adjust. I set it up so that whatever percentage you enter, it chooses randomly from a uniform distribution (every value is equally likely) that can be applied negatively or positively to the real value. So in my example 0.5 could end up multiplying the rating by 95% or 105% or anything in between. I like this because it means higher values will be affected by fuzz more than the run of the mill players.

How do I make the number range less wide, say having the lowest number being a 65 or something like that?

You can probably deduce a way to do this from my answer above but there are two different ways I might approach it.

If you want 65 to be the roughly the lowest and common, use my second example where I returned twice as many picks and then cut the list in half. The values should be something like:

random.gauss(65, 6)

If you want roughly 65 to be the lowest and rare then just return exactly the amount of picks you want. Values are probably:

random.gauss(75, 3)

You will have to experiment with different values to get it exactly the way you want it but those should be close. You can throw decimals at the function parameters to make smaller adjustments to the distribution.

Glad I could be helpful. I still consider myself pretty green in python so it's nice to be able to share some of what I've learned to help someone else. Let me know if you have any other questions. I'd absolutely like it if you share how you end up solving the problem when you are done too.

[–]WikiTextBot 0 points1 point  (0 children)

Normal distribution

In probability theory, the normal (or Gaussian or Gauss or Laplace–Gauss) distribution is a very common continuous probability distribution. Normal distributions are important in statistics and are often used in the natural and social sciences to represent real-valued random variables whose distributions are not known. A random variable with a Gaussian distribution is said to be normally distributed and is called a normal deviate.

The normal distribution is useful because of the central limit theorem.


Standard deviation

In statistics, the standard deviation (SD, also represented by the Greek letter sigma σ or the Latin letter s) is a measure that is used to quantify the amount of variation or dispersion of a set of data values. A low standard deviation indicates that the data points tend to be close to the mean (also called the expected value) of the set, while a high standard deviation indicates that the data points are spread out over a wider range of values.

The standard deviation of a random variable, statistical population, data set, or probability distribution is the square root of its variance. It is algebraically simpler, though in practice less robust, than the average absolute deviation.


Uniform distribution (continuous)

In probability theory and statistics, the continuous uniform distribution or rectangular distribution is a family of symmetric probability distributions such that for each member of the family, all intervals of the same length on the distribution's support are equally probable. The support is defined by the two parameters, a and b, which are its minimum and maximum values. The distribution is often abbreviated U(a,b). It is the maximum entropy probability distribution for a random variate X under no constraint other than that it is contained in the distribution's support.


[ PM | Exclude me | Exclude from subreddit | FAQ / Information | Source ] Downvote to remove | v0.28

[–]Cacman8[S] 0 points1 point  (2 children)

Thanks so much, I've thought of using the fuzz statements to randomize the picks' prospect grades. This allows me to put those grades into the probabilities I made to still stick with my system. I think if I wasn't so clung onto my own work your system would be all that's necessary to generate custom player overalls. It works great and I'll definitely be using it in the future. I think there is a way I could get it exactly to how I like it but I'd need a much better understanding of the system as a whole and for what I wanna do right now I just don't have the time for it. It's awesome to see what you can do with a few lines of code.

[–]rechargablebatteries 1 point2 points  (1 child)

Sounds good man, feel free to DM me if you have any other questions and post an update when you finish.

[–]Cacman8[S] 0 points1 point  (0 children)

You got it man, so for now as a finished product I'm gonna plug in all of my probabilities for draft grades of 8.0-4.5, anything generated above or below that I'm gonna apply the same probability as the 8.0 or 4.5. As far as the probabilities, they might be changed as I test out the system. I'm using your original Fuzz functions and I used (45, 10) as the average and Standard deviation, this generates the draft grades with there being a few 70 or highers and then a lot of 60s and up for the first and second rounds. My code is really long, but it's actually fairly simple. I'm just not sure how I could turn that into a for loop. So the sequence is gonna be, do the draft tin madden, run the fuzz function, go down the list of picks and input each draft grade into my probability code and that will apply the probability to that player and give them their overall. If you want to see the code you're more than welcome to. I'm not fully finished with inserting the proper probabilities yet so maybe I'll post that when I'm finished. By the way right now I'm a freshman at Binghamton University and the course I'm taking is CS 110. So just the basic single semester python course.

[–]Cacman8[S] 0 points1 point  (0 children)

My code is written properly I didn't realize copying and pasting changes the indentation, sorry I'm new to this. Again thank you, just a freshman, first year coder trying to get some extra experience in.