示例#1
0
    def __init__(self, game, name: str, meta: str):
        self._game = game
        self._original_metadata = meta
        self._metadata = MetaParser(type(self)).parse(meta)
        self.name = name
        self.team = self._metadata.team
        self.gender = self._metadata.gender
        self.height = SV.parse(self._metadata.height) if isinstance(
            self._metadata.height,
            str) else SV.parse(str(self._metadata.height) + "m")
        self.baseheight = copy(self.height)
        if not isURL(self._metadata.url):
            raise ValueError(f"{self._metadata.url} is not a URL.")
        self.url = self._metadata.url
        self.attributes = [] if self._metadata.attr is None else self._metadata.attr
        if self._metadata.nsfw is None or self._metadata.nsfw.lower(
        ) == "true":
            self.nsfw = True
        elif self._metadata.nsfw.lower() == "false":
            self.nsfw = False
        else:
            raise ParseError(
                f"{self._metadata.nsfw!r} is not a valid NSFW flag.")

        self.inventory = []
        self.dead = False
        self.elims = 0
示例#2
0
    def parse(cls, s):
        prefixmatch = valid_prefixes + r"\s*(.*)"
        suffixmatch = r"(.*)\s*" + valid_suffixes

        ct = None
        v = None

        if m := re.match(prefixmatch, s):
            prefix = m.group(1)
            value = m.group(2)

            if prefix in add_prefixes:
                ct = "add"
                v = SV.parse(value)
            elif prefix in subtract_prefixes:
                ct = "add"
                v = SV.parse(value) * -1
            elif prefix in multiply_prefixes:
                ct = "multiply"
                v = Decimal(value)
            elif prefix in divide_prefixes:
                ct = "multiply"
                v = Decimal(1) / Decimal(value)
            elif prefix in percent_prefixes:
                ct = "multiply"
                v = Decimal(value) / Decimal(100)
            elif prefix in power_prefixes:
                ct = "power"
                v = Decimal(value)
示例#3
0
    def __init__(self,
                 *,
                 lessthan: str = None,
                 greaterthan: str = None,
                 elimslessthan: str = None,
                 elimsgreaterthan: str = None,
                 elimsequal: str = None,
                 team: str = None,
                 items: list = None,
                 gender: str = None,
                 attributes: list = None,
                 nsfw=None):
        self.lessthan = None if lessthan is None else SV.parse(lessthan)
        self.greaterthan = None if greaterthan is None else SV.parse(
            greaterthan)
        self.elimslessthan = None if elimslessthan is None else Decimal(
            elimslessthan)
        self.elimsgreaterthan = None if elimsgreaterthan is None else Decimal(
            elimsgreaterthan)
        self.elimsequal = None if elimsequal is None else Decimal(elimsequal)
        self.team = team
        self.items = items
        self.attributes = attributes
        self.gender = gender
        self.nsfw = nsfw

        self.realteam = None
示例#4
0
def get_steps(start_inc: SV, diff: Diff, goal: SV):
    """Return the number of steps it would take to reach `goal` from 0,
    first by increasing by `start_inc`, then by `start_inc` operator(`diff.changetype`) `diff.amount`,
    repeating this process until `goal` is reached.

    Returns (steps, final increment, start inc. / final inc.)"""

    if (diff.changetype == "add"
            and diff.amount == 0) or (diff.changetype == "multiply"
                                      and diff.amount == 1):
        if start_inc <= 0:
            return (Decimal("inf"), SV(0), Decimal("inf"))
        # Calculate number of steps required to reach goal
        steps = math.ceil(goal / start_inc)
        # Calculate how far user got after those steps
        # current_pos = start_inc * steps
        return (Decimal(steps), start_inc, 1)
    elif diff.changetype == "add":
        if diff.amount < 0:
            # Calculate max distance travelled, if each step is getting shorter
            max_dist = ((diff.amount / 2) - start_inc) / diff.amount
            if max_dist < goal:
                return (Decimal("inf"), SV(0), Decimal("inf"))
        # Calculate number of steps required to reach goal
        # https://www.wolframalpha.com/input/?i=g+%3D+%28s+*+t%29+%2B+%28a+*+%28%28t+-+1%29+*+t%29+%2F+2%29+solve+for+t
        steps = math.ceil(
            Decimal(
                Decimal(
                    math.sqrt(
                        Decimal(diff.amount**2) -
                        Decimal(4 * diff.amount * start_inc) +
                        Decimal(8 * diff.amount * goal) +
                        Decimal(4 * Decimal(start_inc**2)))) + diff.amount -
                Decimal(2 * start_inc)) / Decimal(2 * diff.amount))
        # Calculate how far user got after those steps
        # current_pos = (start_inc * steps) + (diff.amount * ((steps - 1) * steps) / 2)
        # Calculate length of last step
        current_inc = start_inc + (diff.amount * (steps - 1))
        return (Decimal(steps), current_inc, start_inc / current_inc)
    elif diff.changetype == "multiply":
        # https://en.wikipedia.org/wiki/Geometric_series
        if diff.amount < 1:
            # Calculate max distance travelled, if each step is getting shorter
            max_dist = start_inc / (1 - diff.amount)
            if max_dist < goal:
                return (Decimal("inf"), SV(0), Decimal("inf"))
        # Calculate number of steps required to reach goal
        steps = math.ceil(
            Decimal(
                math.log(-(goal * (1 - diff.amount) / start_inc) + 1,
                         diff.amount)))
        # Calculate how far user got after those steps
        # current_pos = start_inc * ((1 - diff.amount ** (steps - 1)) / (1 - diff.amount))
        # Calculate length of last step
        current_inc = start_inc * (diff.amount**(steps - 1))
        return (Decimal(steps), current_inc, start_inc / current_inc)
    else:
        raise ChangeMethodInvalidException(
            "This change type is not yet supported for scale-walking.")
示例#5
0
 def liftstrength(self, value):
     if value is None:
         self._liftstrength = None
         return
     value = SV(value)
     if value < 0:
         value = SV(0)
     self._liftstrength = value
示例#6
0
    def change_height(self, diff: Diff):
        if diff.changetype == "add":
            self.height = SV(self.height + diff.amount)
        elif diff.changetype == "multiply":
            self.height = SV(self.height * diff.amount)

        else:
            raise GametimeError(f"Unsupported changetype {diff.changetype!r}.")
示例#7
0
 def hairlength(self, value):
     if value is None:
         self._hairlength = None
         return
     value = SV(value)
     if value < 0:
         value = SV(0)
     self._hairlength = value
示例#8
0
 def __init__(self, userid, guildid, *, addPerSec=0, mulPerSec=1, stopSV=None, stopTV=None, startTime=None, lastRan=None):
     self.userid = userid
     self.guildid = guildid
     self.addPerSec = addPerSec and SV(addPerSec)
     self.mulPerSec = mulPerSec and Decimal(mulPerSec)
     self.stopSV = stopSV and SV(stopSV)
     self.stopTV = stopTV and TV(stopTV)
     self.startTime = startTime and Decimal(startTime)
     self.lastRan = lastRan and Decimal(lastRan)
示例#9
0
def get_dist(start_inc: SV, diff: Diff, steps: int):
    if diff.changetype == "add":
        current_pos = (start_inc * steps) + (diff.amount *
                                             ((steps - 1) * steps) / 2)
        return SV(current_pos)
    elif diff.changetype == "multiply":
        current_pos = start_inc * ((1 - diff.amount**(steps - 1)) /
                                   (1 - diff.amount))
        return SV(current_pos)
    else:
        raise ChangeMethodInvalidException(
            "This change type is not yet supported for scale-walking.")
示例#10
0
    async def setear(self, ctx, *, newear):
        """Set your current ear heightear."""
        userdata = userdb.load(ctx.guild.id, ctx.author.id, allow_unreg=True)

        newearsv = SV(SV.parse(newear) * userdata.viewscale)

        userdata.earheight = newearsv
        userdb.save(userdata)

        await ctx.send(
            f"{userdata.nickname}'s base ear height is now {userdata.earheight:mu} long, "
            f"or {SV(userdata.earheight):mu} currently.")
        await showNextStep(ctx, userdata)
示例#11
0
    async def setfoot(self, ctx, *, newfoot):
        """Set your current foot length."""

        userdata = userdb.load(ctx.guild.id, ctx.author.id, allow_unreg=True)

        userdata.footlength = SV(SV.parse(newfoot) * userdata.viewscale)
        userdb.save(userdata)

        await ctx.send(
            f"{userdata.nickname}'s base foot length is now {userdata.footlength:mu} long ({formatShoeSize(userdata.footlength)}), "
            f"or {(SV(userdata.footlength * userdata.scale)):mu} currently. {formatShoeSize(SV(userdata.footlength * userdata.scale))}"
        )
        await showNextStep(ctx, userdata)
示例#12
0
    async def settail(self, ctx, *, newtail):
        """Set your current tail length."""
        userdata = userdb.load(ctx.guild.id, ctx.author.id, allow_unreg=True)

        newtailsv = SV(SV.parse(newtail) * userdata.viewscale)

        userdata.taillength = newtailsv
        userdb.save(userdata)

        await ctx.send(
            f"{userdata.nickname}'s base tail length is now {userdata.taillength:mu} long, "
            f"or {SV(userdata.taillength):mu} currently.")
        await showNextStep(ctx, userdata)
示例#13
0
    async def settail(self, ctx, *, newtail):
        """Set your current tail length."""
        userdata = userdb.load(ctx.guild.id, ctx.author.id)

        newtailsv = SV(SV.parse(newtail) * userdata.viewscale)

        userdata.taillength = newtailsv
        userdb.save(userdata)

        logger.info(
            f"User {ctx.author.id} ({ctx.author.display_name})'s tail is now {userdata.taillength:m} long."
        )
        await ctx.send(
            f"<@{ctx.author.id}>'s tail is now {userdata.taillength:mu} long.")
示例#14
0
    async def setfoot(self, ctx, *, newfoot):
        """Set your current foot length."""

        userdata = userdb.load(ctx.guild.id, ctx.author.id)

        userdata.footlength = SV(SV.parse(newfoot) * userdata.viewscale)
        userdb.save(userdata)

        logger.info(
            f"User {ctx.author.id} ({ctx.author.display_name})'s foot is now {userdata.footlength:m} long."
        )
        await ctx.send(
            f"<@{ctx.author.id}>'s foot is now {userdata.footlength:mu} long. ({formatShoeSize(userdata.footlength)})"
        )
示例#15
0
def getUserSizes(g):
    # Find the largest and smallest current users.
    smallestuser = None
    smallestsize = SV.infinity
    largestuser = None
    largestsize = SV(0)
    allusers = {}
    for _, userid in userdb.listUsers(guildid=g.id):
        member = g.get_member(userid)
        if not (member and str(member.status) != "offline"):
            continue
        userdata = userdb.load(g.id, userid)
        if userdata.height == 0 or userdata.height == SV.infinity:
            continue
        if not userdata.is_active:
            continue
        if userdata.height > largestsize:
            largestuser = userid
            largestsize = userdata.height
        if userdata.height < smallestsize:
            smallestuser = userid
            smallestsize = userdata.height
        allusers[userid] = userdata.height
    return {
        "smallest": {
            "id": smallestuser,
            "size": smallestsize
        },
        "largest": {
            "id": largestuser,
            "size": largestsize
        },
        "users": allusers
    }
示例#16
0
    async def ruler(self, ctx, length: SV, *, who: typing.Union[discord.Member, SV] = None):
        """A distance to a user looks how long to everyone else?

        Examples:
        `&ruler 1mi`
        `&ruler 1ft @DigiDuncan`"""

        if who is None:
            who = ctx.message.author

        userdata = getUserdata(who)
        userstats = proportions.PersonStats(userdata)

        if userdata.height == 0:
            await ctx.send(f"{userdata.tag} doesn't exist...")
            return

        newlength = SV(length / userstats.viewscale)

        e = discord.Embed(
            title = f"{userstats.nickname}'s {length:,.3mu} to the world",
            description = (
                f"To everyone else, {userstats.nickname}'s {length:,.3mu} would look to be **{newlength:,.3mu}.**"
            )
        )

        await ctx.send(embed = e)
示例#17
0
def SV_parse():
    s = request.args.get("s")
    try:
        val = SV.parse(s)
    except InvalidSizeValue:
        abort(404)
    return json.dumps({"SV": str(val)})
示例#18
0
    async def setbase(self,
                      ctx,
                      arg1: typing.Union[SV, WV],
                      arg2: typing.Union[SV, WV] = None):
        """Set your base height and weight."""
        userdata = userdb.load(ctx.guild.id, ctx.author.id, allow_unreg=True)

        # Don't allow a user to enter setbase(SV, SV) or setbase(WV, WV)
        if (isinstance(arg1, SV)
                and isinstance(arg2, SV)) or (isinstance(arg1, WV)
                                              and isinstance(arg2, WV)):
            raise errors.UserMessedUpException(
                "Please do not enter two heights or two weights.")

        newbaseheight = None
        newbaseweight = None
        for arg in [arg1, arg2]:
            if isinstance(arg, SV):
                newbaseheight = arg
            if isinstance(arg, WV):
                newbaseweight = arg
        completed_registration = False
        if newbaseheight is not None:
            if "setheight" in userdata.registration_steps_remaining:
                userdata.height = newbaseheight
                if not (SV.parse("4ft") < newbaseheight < SV.parse("8ft")):
                    await ctx.send(
                        f"{emojis.warning} **WARNING:** Your base height should probably be something more human-scale. This makes comparison math work out much nicer. If this was intended, you can ignore this warning, but it is ***highly recommended*** that you have a base height similar to the size of a normal human being."
                    )
            userdata.baseheight = newbaseheight
            completed_registration = userdata.complete_step(
                "setheight") or completed_registration
        if newbaseweight is not None:
            if "setweight" in userdata.registration_steps_remaining:
                if not (WV.parse("10lb") < newbaseheight < SV.parse("1000lb")):
                    await ctx.send(
                        f"{emojis.warning} **WARNING:** Your base weight should probably be something more human-scale. This makes comparison math work out much nicer. If this was intended, you can ignore this warning, but it is ***highly recommended*** that you have a base weight similar to that of a normal human being."
                    )
            userdata.baseweight = newbaseweight
            completed_registration = userdata.complete_step(
                "setweight") or completed_registration
        userdb.save(userdata)

        await ctx.send(
            f"{userdata.nickname} changed their base height and weight to {userdata.baseheight:,.3mu} and {userdata.baseweight:,.3mu}"
        )
        await showNextStep(ctx, userdata, completed=completed_registration)
示例#19
0
def SV_format():
    value = Decimal(request.args.get("value"))
    system = request.args.get("system")
    try:
        val = SV(value)
    except InvalidSizeValue:
        abort(404)
    return json.dumps({"formatted": format(val, system)})
示例#20
0
async def on_message(m):
    # non-guild messages
    if not isinstance(m.author, discord.Member):
        return

    edgedict = getEdgesFile(m.guild.id)
    sm = edgedict.get("smallest", None)
    lg = edgedict.get("largest", None)
    if m.author.id != sm and m.author.id != lg:
        return  # The user is not set to be the smallest or the largest user.

    userdata = userdb.load(m.guild.id, m.author.id)

    usersizes = getUserSizes(m.guild)
    smallestuser = usersizes["smallest"]["id"]
    smallestsize = usersizes["smallest"]["size"]
    largestuser = usersizes["largest"]["id"]
    largestsize = usersizes["largest"]["size"]

    if edgedict.get("smallest", None) == m.author.id:
        if m.author.id == smallestuser:
            return
        elif userdata.height == SV(0):
            return
        else:
            userdata.height = smallestsize * Decimal(0.9)
            userdb.save(userdata)
            logger.info(
                f"User {m.author.id} ({m.author.display_name}) is now {userdata.height:m} tall, so that they stay the smallest."
            )

    if edgedict.get("largest", None) == m.author.id:
        if m.author.id == largestuser:
            return
        elif userdata.height == SV(SV.infinity):
            return
        else:
            userdata.height = largestsize * Decimal(1.1)
            userdb.save(userdata)
            logger.info(
                f"User {m.author.id} ({m.author.display_name}) is now {userdata.height:m} tall, so that they stay the largest."
            )

    if userdata.display:
        await proportions.nickUpdate(m.author)
示例#21
0
    def fromJSON(cls, jsondata):
        changetype = jsondata["changetype"]
        if changetype == "add":
            amount = SV(jsondata["amount"])
        else:
            amount = Decimal(jsondata["amount"])
        original = jsondata["original"]

        return cls(original, changetype, amount)
示例#22
0
    def addToUnits(self):
        if self.unitlength is not None:
            SV.addUnit(
                Unit(factor=self.unitlength,
                     name=self.name,
                     namePlural=self.namePlural,
                     names=self.aliases,
                     symbol=self.symbol))
            SV.addSystemUnit("o", SystemUnit(self.name))

        if self.weight is not None:
            WV.addUnit(
                Unit(factor=self.weight,
                     name=self.name,
                     namePlural=self.namePlural,
                     names=self.aliases,
                     symbol=self.symbol))
            WV.addSystemUnit("o", SystemUnit(self.name))
示例#23
0
    def runperhour(self, value):
        if value is None:
            self._runperhour = None
            return

        if isinstance(value, ParseableRate):
            if value.diff.changetype != "add":
                raise ValueError("Invalid rate for speed parsing.")
            if value.diff.amount < 0:
                raise ValueError("Speed can not go backwards!")
            value = value.diff.amount / value.time * Decimal("3600")

        value = SV(value)

        if value < 0:
            value = SV(0)

        self._runperhour = value
示例#24
0
def fromShoeSize(shoesize):
    shoesizenum = Decimal(re.search(r"(\d*,)*\d+(\.\d*)?", shoesize)[0])
    if "w" in shoesize.lower():
        shoesizenum -= 1
    if "c" in shoesize.lower(
    ):  # Intentional override, children's sizes have no women/men distinction.
        shoesizenum -= (12 + Decimal("1/3"))
    footlengthinches = ((shoesizenum + 24) / 3) - Decimal("2/3")
    return SV.parse(f"{footlengthinches}in")
示例#25
0
    async def load(self, data: str):
        self.parser = Parser(self.game, data)

        async for progress in self.parser.parse():
            yield progress

        self.minsize = SV.parse(
            "1mm") if self.parser.minsize is None else SV.parse(
                self.parser.minsize)
        self.maxsize = SV.parse(
            "4mi") if self.parser.maxsize is None else SV.parse(
                self.parser.maxsize)
        self.autoelim = True if self.parser.autoelim is None else bool(
            self.parser.autoelim)
        self.deathrate = Decimal(
            10) if self.parser.deathrate is None else Decimal(
                self.parser.deathrate)
        self.arenafreq = Decimal(
            10) if self.parser.deathrate is None else Decimal(
                self.parser.deathrate)
        self.unitsystem = "m" if self.parser.unitsystem is None else self.parser.unitsystem
        self.teamwin = False if self.parser.teamwin is None else bool(
            self.parser.teamwin)

        self.players = self.parser.players
        self.original_player_count = len(self.players)

        self.arenas = self.parser.arenas

        self._bloodbath_events = self.parser.bloodbath_events
        self._day_events = self.parser.day_events
        self._night_events = self.parser.night_events
        self._fatalday_events = self.parser.fatalday_events
        self._fatalnight_events = self.parser.fatalnight_events
        self._feast_events = self.parser.feast_events
        eventsdict = {
            "bloodbath_events": self._bloodbath_events,
            "day_events": self._day_events,
            "night_events": self._night_events,
            "fatalday_events": self._fatalday_events,
            "fatalnight_events": self._fatalnight_events,
            "feast_events": self._feast_events
        }
        self.events = AttrDict(eventsdict)
示例#26
0
def changeUser(guildid, userid, changestyle, amount):
    changestyle = changestyle.lower()
    if changestyle in ["add", "+", "a", "plus"]:
        changestyle = "add"
    if changestyle in ["subtract", "sub", "-", "minus"]:
        changestyle = "subtract"
    if changestyle in ["power", "exp", "pow", "exponent", "^", "**"]:
        changestyle = "power"
    if changestyle in ["multiply", "mult", "m", "x", "times", "*"]:
        changestyle = "multiply"
    if changestyle in ["divide", "d", "/", "div"]:
        changestyle = "divide"
    if changestyle in ["percent", "per", "perc", "%"]:
        changestyle = "percent"

    if changestyle not in [
            "add", "subtract", "multiply", "divide", "power", "percent"
    ]:
        raise errors.ChangeMethodInvalidException(changestyle)

    amountSV = None
    amountVal = None
    newamount = None

    if changestyle in ["add", "subtract"]:
        amountSV = SV.parse(amount)
    elif changestyle in ["multiply", "divide", "power"]:
        amountVal = Decimal(amount)
        if amountVal == 1:
            raise errors.ValueIsOneException
        if amountVal == 0:
            raise errors.ValueIsZeroException
    elif changestyle in ["percent"]:
        amountVal = Decimal(amount)
        if amountVal == 0:
            raise errors.ValueIsZeroException

    userdata = userdb.load(guildid, userid)

    if changestyle == "add":
        newamount = userdata.height + amountSV
    elif changestyle == "subtract":
        newamount = userdata.height - amountSV
    elif changestyle == "multiply":
        newamount = userdata.height * amountVal
    elif changestyle == "divide":
        newamount = userdata.height / amountVal
    elif changestyle == "power":
        userdata = userdata**amountVal
    elif changestyle == "percent":
        newamount = userdata.height * (amountVal / 100)

    if changestyle != "power":
        userdata.height = newamount

    userdb.save(userdata)
示例#27
0
    async def setrandomheight(self, ctx, minheight, maxheight):
        """Change height to a random value.

        Sets your height to a height between `minheight` and `maxheight`.
        Weighted on a logarithmic curve."""
        minheightSV = utils.clamp(0, SV.parse(minheight), SV._infinity)
        maxheightSV = utils.clamp(0, SV.parse(maxheight), SV._infinity)

        newheightSV = decimal.randRangeLog(minheightSV, maxheightSV)

        userdata = userdb.load(ctx.guild.id, ctx.author.id)

        userdata.height = newheightSV
        userdb.save(userdata)

        logger.info(
            f"User {ctx.author.id} ({ctx.author.display_name}) set a random height, and are now {userdata.height:m} tall."
        )
        await ctx.send(f"<@{ctx.author.id}> is now {userdata.height:mu} tall.")

        await proportions.nickUpdate(ctx.author)
示例#28
0
    async def setinf(self, ctx):
        """Change height to infinity."""
        userdata = userdb.load(ctx.guild.id, ctx.author.id, allow_unreg=True)

        userdata.height = SV("infinity")
        completed_registration = userdata.complete_step("setheight")
        userdb.save(userdata)

        await ctx.send(f"{userdata.nickname} is now infinitely tall.")

        await proportions.nickUpdate(ctx.author)
        await showNextStep(ctx, userdata, completed=completed_registration)
示例#29
0
    def fromJSON(cls, jsondata):
        rate = Rate.fromJSON(jsondata["rate"])
        original = jsondata["original"]
        stoptype = jsondata["stoptype"]
        if stoptype == "SV":
            stop = SV(jsondata["stop"])
        elif stoptype == "TV":
            stop = TV(jsondata["stop"])
        else:
            raise ThisShouldNeverHappenException

        return cls(original, rate, stop)
示例#30
0
    async def setbaseear(self, ctx, *, newear):
        """Set a custom ear height."""
        newearsv = SV.parse(newear)

        userdata = userdb.load(ctx.guild.id, ctx.author.id, allow_unreg=True)

        userdata.earheight = newearsv
        userdb.save(userdata)

        await ctx.send(
            f"{userdata.nickname}'s ear is now {userdata.earheight:mu} long.")
        await showNextStep(ctx, userdata)