coding-buddies-discord / cb-bots

4 stars 3 forks source link

Point System Data Model #8

Closed waream2 closed 1 year ago

waream2 commented 2 years ago

Proposal

Here is the proposed model for the Points System for the bot:

points: {
       userId: {
           pointsGiven: number,
           pointsReceived: number,
       },
       userId: {
           pointsGiven: number,
           pointsReceived: number,
       },
     ...
    };

We could then utilize the newMemberAdd event to add a new user to the database every time a user is added to the server. We'd also use the suffix ++ to trigger a message event that would understand 1) who sent the message, and increment their pointsGiven by one and 2) parse who was mentioned in the message and increment their pointsReceived by one.

Also the bot will respond and give that person kudos, along with display their total points.

db.js will expose methods to interact with the database in this way. These methods will be called when a new user join the server and when someone sends a message with the suffix after a valid userID.

Risks

cubiquitous commented 2 years ago

is not clear to me where "pointsGiven" could be used.

regarding the risks: 1 - is true that people could span themselves, but this should be easy to solve. 2 - i think that we just need to add a new user when somebody gives a new point. something like points[user] += 1

waream2 commented 2 years ago

I think pointsGiven is just a useful metric to how engaged people are in the server. e.g. who's asking questions and giving points. No real use for it right now but creating it for possible future use, would hate to lose that data.

agree on point two, youre saying if the user isnt in the database then create them, if they are then add a point?

cubiquitous commented 2 years ago

I think pointsGiven is just a useful metric to how engaged people are in the server.

alright

agree on point two, youre saying if the user isnt in the database then create them, if they are then add a point?

yes. I think that this way is easier this way.

now, something appeared in my head, if I change my does the bot uses the userName? if so, if I change my name from let's say cub16 to cub, how would we deal with this?

doulovera commented 2 years ago

If we use the userId, there is no problem, that doesn't change and we can get the username with that

cubiquitous commented 2 years ago

I forgot to say it earlier, but if we may want to use this db to store the last people who gave points to the user. it would be something like:

points: {
       userId: {
           pointsGiven: number,
           pointsReceived: number,
           lastPointsGiveBy: [userID, userID]
       },
    };

however @consecutes pointed that we may wanna use a global history of posts and just check it against this global. feel free to correct me.

I personally prefer each user with it's own list of points given. i think that scales better this way

cubiquitous commented 2 years ago

I forgot to say it earlier, but if we may want to use this db to store the last people who gave points to the user. it would be something like:

points: {
       userId: {
           pointsGiven: number,
           pointsReceived: number,
           lastPointsGiveBy: [userID, userID]
       },
    };

however @consecutes pointed that we may wanna use a global history of posts and just check it against this global. feel free to correct me.

I personally prefer each user with it's own list of points given. i think that scales better this way

cubiquitous commented 2 years ago

small correction:

points: {
       userId: {
           pointsGiven: number,
           pointsReceived: number,
           lastPointsGiveBy: [{ userID: number, date: Date }, { userID: number, date: Date }, ]
       },
    };

that way we would have the dates and username to compare. but of course, this change would be relevant only if we follow my idea of having an queue-like structure for the points received by what user.

waream2 commented 2 years ago

I like the idea of capturing this data 100%, what do you see as this use for having this array?

waream2 commented 2 years ago

This leads to another question, do we want to keep track of which channel points where given in? This way we'd have the ability to see who's answering questions in what channel, say css+html javascript react python etc.

cubiquitous commented 2 years ago

I like the idea of capturing this data 100%, what do you see as this use for having this array?

well, we need to compare the last user that gave the point to guarantee that the user don't give twice in a row. but knowing only the user wont be good, we also need the date, so we can compare if the point given was around the time limit (as previously discussed in the group).

however, we need to do not only for the last message, but for multiple messages, otherwise someone could do something like:

@waream
@cub
@waream

and it would pass; the way that I wrote can solve those problems since you can analyze based on the time and person who gave, for multiple people.

cubiquitous commented 2 years ago

This leads to another question, do we want to keep track of which channel points where given in? This way we'd have the ability to see who's answering questions in what channel, say css+html javascript react python etc.

I had the same question in regards to the scoreboard, but decided to move on, because it may become tricky to create new channels and keep track. unless someone has a way to solve this.

doulovera commented 2 years ago

I think storing the channel where the point was given is a good idea

waream2 commented 2 years ago

@Claudi0-V I think we can store date as a timestamp and if there's a timestamp within say 1 minute of another one, we dont run the function. It will be one of the checks that we do at the top of the command.

I think we can solve new channels with an event here When this event fires, we just add it to the database. But that means we need a new model to account for all the channels.

Things sure do stack up quickly 😅.

waream2 commented 2 years ago

So here's where I think we are as of right now:

points: {
       userId: {
           pointsGiven: number,
           pointsReceived: number,
           lastPointsGiveBy: [{ userID: number, date: Date (timestamp) }, { userID: number, date: Date(timestamp) }, ],
           channels: [strings],
       },
    };

Channels can just be an array that the channel name gets pushed to every time they get a point? Feels like trying to create a model that adds new channels every time a channel is added and then goes through and updates each user object is overkill.

In this way, channels.length should equal pointsReceived at any given time.

doulovera commented 2 years ago

And what if we store the pointsReceived as an array of objects?

points: {
  {userId}: {
    pointsReceived: [{
      givenBy: userId,
      date: '2022-02-14',
      channel: '#javascript',
    }],
    ...
  }
}
waream2 commented 2 years ago

You my friend, are much smarter than I. That has my vote, so much cleaner.

waream2 commented 2 years ago

That begs the question, do we do the same with points given? I dont see why not? It can follow the exact same model.

doulovera commented 2 years ago

Yes! For the points given will be great too

waream2 commented 2 years ago

@doulovera 's suggestion seems like the winner. @Claudi0-V @consecutes, if you all are cool. We will lock in the spec and move forward.

cubiquitous commented 2 years ago

I'm almost ok with it, but I don't see the need to save who give the point and when. my idea of using lastPointsGiveBy: [{ userID: number, date: Date } ] was because we can use .filter() to remove the ones that are too old, thus removing permanently from the array, and then .some()to see if some of the lasting pass or not.

I think that the way proposed by @doulovera makes a bit harder to check those dates. there's any point to save the "dates" and "givenBy"?

waream2 commented 2 years ago
points: {
  {userId}: {
    pointsReceived: [{
      givenBy: id,
      date: timestamp,
      channel: string,
    }],
    pointsGiven: [{
      givenTo: id,
      date: timestamp,
      channel: string,
    }],
    lastPointsGiveBy: [{ 
      userID: number, 
      date: timestamp, 
   }]
}

@Claudi0-V does this fix that?

waream2 commented 2 years ago

@doulovera you cool with this change? If so, that gives us 3/4 saying yes and we'll lock it in as v 0.0.1 of the schema.

cubiquitous commented 2 years ago

@Claudi0-V does this fix that?

i guess that if you need that givenBy and date on points received and given, then yes. otherwise I would suggest it to be:

points: {
  {userId}: {
    pointsReceived: [{
      givenBy: userId,
      date: '2022-02-14',
      channel: '#javascript',
    }],
    pointsGiven: {
    '#javascript': 0,
    'html+css' : 0,
    }
    lastPointsGiveBy: [{ userID: number, date: Date (timestamp) }, { userID: number, date: Date(timestamp) }, ]
  }
}
waream2 commented 2 years ago

I think we should be as verbose as possible with data collection at first. Would rather get down the road and have it and not need it, than need it and not have it.

Let's collect everything and scale back if needed.

cubiquitous commented 2 years ago

no objections then