How can I make a demand command loop? - python-3.x

I have a command named demand and need to make a limit to amounts per user. There are roles in the server named "team_role" and then there's also "2 demands", "1 demand", and "0 demands". After the user demands, I need it to role them down a demand until eventually, they hit 0. Once they hit 0, it should send them a message saying they can't demand. Here's my code for one of the teams (the Dallas Cowboys).
#bot.command(aliases=["<:DallasCowboys:788796627161710592>"])
#commands.has_any_role("Dallas Cowboys")
async def t(ctx):
guild = bot.get_guild(766292887914151949)
role_name = discord.utils.get(guild.roles, name='Free Agent')
role = discord.utils.get(guild.roles, name='Dallas Cowboys')
embed = discord.Embed()
embed.add_field(name="<a:CheckMark:768095274949935146> Successful Demand", value=f"{ctx.author.mention} has demanded from the <:DallasCowboys:788796627161710592>")
await ctx.send(embed=embed)
await ctx.author.add_roles(role_name)
await ctx.author.remove_roles(role)

Since you said I can just provide the logic:
Create a means of persistently storing the data, whether that be
json file or a database.
a) If you choose the json file, the file will consist of key value
pairs of user ids to number of demands remaining. For example, the
file might look something like this:
{ "UserDemandsRemaining" : { 12345 : 2, 45678: 1, 09876: 0 } }
b) If you choose to use to use a SQL database, create a table called
UserDemandsRemaining with two fields: UserId and
DemandsRemaining. The primary key would be UserId.
Each time a user makes a demand, you will check how many remaining
demands the user has.
If there is no matching UserId stored:
a) If you chose to use a json file, and there is no matching key in the json value associated with the UserDemandsRemaining key, then create a key-value pair with the key as the UserId that made the demand, and the value as 3.
b) If you chose to use a SQL db, and there is no matching UserId matching the UserId that made the demand in the UserDemandsRemaining table of the database, then insert a row into the table containing the UserId that made the demand and a DemandsRemaining value of 3.
Since the user isn't stored, we know that they have not yet made any demands. Execute the demand. Then decrement the `DemandsRemaining` by 1.
Else if there is a matching UserId:
if DemandsRemaining > 0:
#Execute the command. Decrement `DemandsRemaining` by 1.
else:
#Notify the user that they have no more remaining demands.
In order to reset the number of demands each person has remaining,
just set the value pair associated with the users in the json file
or the DemandsRemaining in the table to 3 for everyone.

Related

Django validate the input as a valid foreign key

In django rest framework, have a POST api that creates a City object.
However it also receives a list of ids of stadiums.
What is the best way to validate each of the ids are valid stadium_ids (present and not deleted in the table Stadiums).
First put list of ids in a set to distinct probable repeated ids:
ids = set(ids)
Then filter stadiums based on this ids:
stadiums = Stadium.object.filter(id__in=ids)
If some stadiums are not present in database, then count of stadiums is less than size of ids:
if len(ids) != len(stadiums):
# Handle Error

Getting index of the resultset

Is there a way to get the index of the results within an aql query?
Something like
FOR user IN Users sort user.age DESC RETURN {id:user._id, order:{index?}}
If you want to enumerate the result set and store these numbers in an attribute order, then this is possible with the following AQL query:
LET sorted_ids = (
FOR user IN Users
SORT user.age DESC
RETURN user._key
)
FOR i IN 0..LENGTH(sorted_ids)-1
UPDATE sorted_ids[i] WITH { order: i+1 } IN Users
RETURN NEW
A subquery is used to sort users by age and return an array of document keys. Then a loop over a numeric range from the first to the last index of the that array is used to iterate over its elements, which gives you the desired order value (minus 1) as variable i. The current array element is a document key, which is used to update the user document with an order attribute.
Above query can be useful for a one-off computation of an order attribute. If your data changes a lot, then it will quickly become stale however, and you may want to move this to the client-side.
For a related discussion see AQL: Counter / enumerator
If I understand your question correctly - and feel free to correct me, this is what you're looking for:
FOR user IN Users
SORT user.age DESC
RETURN {
id: user._id,
order: user._key
}
The _key is the primary key in ArangoDB.
If however, you're looking for example data entered (in chronological order) then you will have to have to set the key on your inserts and/or create a date / time object and filter using that.
Edit:
Upon doing some research, I believe this link might be of use to you for AI the keys: https://www.arangodb.com/2013/03/auto-increment-values-in-arangodb/

How do I read write a content item in a separate database transaction to that of the request

I have a Purchase Order content type in my Orchard application. Among other properties it has a PurchaseOrderNumber. The purchase order number is assigned when the user saves the purchase order for the first time. I use a custom controller and views for implementing the purchase order CRUD operations.
I have a purchase order number definition part which is attached to a company content type where the next purchase order number, a prefix and padding is saved. So when the system generates the next purchase order number, the prefix (e.g. PO) is used together with the next number (e.g. 123) and the padding (e.g. 5) to generate a string - e.g. PO00123.
When the purchase order number is generated the next purchase order number stored in the purchase order definition part attached to the company content item is incremented and saved so that when a user creates another purchase order it will be assigned the next number.
My challenge here is to prevent duplicate purchase order numbers from being assigned if two users create a new purchase order at the same time.
I was thinking of creating an ISingletonDependency that uses lock (_lock) {...} to wrap code that will generate the next number. This way multiple request can ask for the next number and always get the next unique number. How do I implement this though? I can't figure out how to get access to an IContentManager that has its own database transaction.
Or is there a different pattern that I should rather use?
I figured it out after looking at the Orchard.Tasks.Locking.Services.DistributedLockService class. You need to take a dependency on ILifetimeScope and then resolve ITransactionManager and IContentManager.
lock (_lock) {
using (var childLifetimeScope = _lifetimeScope.BeginLifetimeScope()) {
var transactionManager = childLifetimeScope.Resolve<ITransactionManager>();
var contentManager = childLifetimeScope.Resolve<IContentManager>();
try {
transactionManager.RequireNew(IsolationLevel.Serializable);
var contentItem = contentManager.GetLatest(contentItemId);
var number = CompileNewNumber(contentItem);
contentManager.Publish(contentItem);
return number;
}
catch (Exception exception) {
Logger.Error(exception, "Error compiling next number.");
transactionManager.Cancel();
return "";
}
}
}

Cloudant 1 to many function

I’ve just started to use Cloudant and I just can’t get my head around the map functions. I’ve been fiddling with the data below but it isn’t working out as I expected.
The relationship is, a user can have many vehicles. A vehicle belongs to 1 user. The vehicle ‘userId’ is the key of the user. There is a bit of redundancy as in user the _id and userId is the same, guess later is not required.
Anyhow, how can I find for a/every user, the vehicles which belong to it? The closest I’ve come through trial and error is a result which displays the owner of every vehicle, but I would like it the other way round, the user and the vehicles belonging to it. All the examples I’ve found use another document which ‘joins’ two or more documents, but I don’t need to do that?
Any point in the right direction appreciated - I really have no idea.
function (doc) {
if (doc.$doctype == "vehicle")
{
emit(doc.userId, {_id: doc.userId});
}
}
EDIT: Getting closer. I'm not sure exactly what I was expecting, but the result seems a bit 'messy'. Row[0] is the user document, row[n > 0] are the vehicle documents. I guess it's fine when a startkey/endkey is used, but without the results are a bit jumbled up.
function (doc) {
if (doc.$doctype == 'user') {
emit([doc._id, 0], doc);
} else if (doc.$doctype == 'vehicle') {
emit([doc.userId, 1, doc._id], doc);
}
}
A user is described as,
{
"_id": "user:10",
"firstname": “firstnamehere",
"secondname": “secondnamehere",
"userId": "user:10",
"$doctype": "user"
}
a vehicle is described as,
{
"_id": "vehicle:4002”,
“name”: “avehicle”,
"userId": "user:10",
"$doctype": "vehicle",
}
You're getting in the right direction! You already got that right with the global IDs. Having the type of the document as part of the ID in some form is a very good idea, so that you don't get confused later (all documents are in the same "pot").
Here are some minor problems with your current solution (before getting to your actual question):
Don't emit the doc as value in emit(key, value). You can always ask for the document that belongs to a view row by querying with include_docs=true. Having the doc as view value increases the view indexes a lot. When you don't need a specific value, use emit(key, null).
You also don't need the ID in the emit value. You'll get the ID of the document that belongs to a view row as part of the row anyway.
View Collation
Now to your problem of aggregating the vehicles with their user. You got the basic pattern right. This pattern is called view collation, you can read more about it in the CouchDB docs (ignore that it is in the "Couchapp" section).
The trick with view collation is that you return two or more types of documents, but make sure that they are sorted in a way that allows for direct grouping. Thus it is important to understand how CouchDB sorts the view result. See the collation specification for more information on that one. An important key to understanding view collation is that rows with array keys are sorted by key elements. So when two rows have the same key[0], they sort by key[1]. If that's equal as well, key[2] is considered, and so on.
Your map function frist groups users and vehicles by user ID (key[0]). Your map function then uses the fact that 0 sorts before 1 in the second element of the key, so your view will contain the following:
user 1
vehicle of user 1
vehicle of user 1
vehicle of user 1
user 2
user 3
vehicle of user 3
user 4
etc.
As you can see, the vehicles of a user immediately follow their user. Thus you can group this result into aggregates without performing expensive sort or lookup operations.
Note that users are sorted according to their ID, and vehicles within users also according to their ID. This is because you use the IDs in the key array.
Creating Queries
Now that view isn't worth much if you can't query according to your needs. A view as you have it supports the following queries:
Get all users with their vehicles
Get a range of users with their vehicles
Get a single user with its vehicles
Get a single user without vehicles (you could also use the _all_docs view for that though)
Example query for "all users between user 1 and user 3 (inclusive) with their vehicles"
We want to query for a range, so we use startkey and endkey in the query:
startkey=["user:1", 0]
endkey=["user:3", 1, {}]
Note the use of {} as sentinel value, which is required so that the end key is larger than any row that has a key of ["user:3", 1, (anyConceivableVehicleId)]

Query Trac for all tickets related to a user

How do I query for all trac tickets related to a user. i.e. all tickets for which the tickets were once assigned, assigned now, created , etc etc
Create custom queries to the ticket_change table. Some SQL required. For assigned once/now, look for rows where field='owner', newvalue column contains the user name the ticket was assigned to. For created tickets, just query by reporter in the ticket table.
Example:
SELECT p.value AS __color__,
id AS ticket, summary, component, version, milestone,
t.type AS type, priority, t.time AS created,
changetime AS _changetime, description AS _description,
reporter AS _reporter
FROM ticket t, enum p, ticket_change c
WHERE p.name = t.priority AND p.type = 'priority'
AND c.field = 'owner'
AND c.newvalue = '$USER'
AND c.ticket = t.id
ORDER BY p.value, milestone, t.type, t.time
You can express this with a TraqQuery expression. E.g. if you want the columns id, summary and status to show up and query all the tickets for the currently logged in user ($USER) then use the following query.
query:?col=id
&
col=summary
&
col=status
&
owner=$USER
However this query assumes that the owner hasn't been the same during the lifetime of a ticket (since ownership can be changed).
If you want a specific user then replace $USER with the actual username. Also if you're using the Agilo plugin you can easily create new queries on the fly via the web-UI. This is done by looking at a report and adding filters to the report.

Resources