Determining Turn Order - python

I wanted to try it like this, but I don't want to nest a bunch of for loops or if statements. For some reason I'm not seeing what the actual comparison should be to take the speeds list and populate turn order. Basically just comparing what each individual minion's speed is against the others using the sort function in it's own method and returning a list. Then I want to compare the list values against the key values stored in the minion_collection. I'm not sure if I'm setting myself up for a world of hurt here or not. Still somewhat new to python so I don't know many of the utilities.
minion_collection = {
'minion1' : {
"name" : "zombie", "str" : 10, "def" : 5, "hp" : 25, "maxhp" : 25, "speed" : 15, "spdbar": 0},
'minion2' : {
"name": 'cleric', "str": 4, "def": 5, "hp": 25,"maxhp": 25, "speed": 20, "spdbar": 0},
'minion3' : {
"name" : "professor", "str" : 10, "def" : 5, "hp" : 25, "maxhp" : 25, "speed" : 15, "spdbar": 0},
'minion4' : {
"name": 'hunter', "str": 4, "def": 5, "hp": 25,"maxhp": 25, "speed": 30, "spdbar": 0}
}
def initiative(speeds):
for x in minion_collection:
minion_collection[x]['spdbar'] = 100
order = sort(speeds, reverse = True)
return order
Where I start to determine the turn order
turn = 1
speeds = (fighter1['speed'], fighter2['speed'], pcfighter1['speed'], pcfighter2['speed'])
order = initiative(speeds)
for speed in order:
if fighter1['speed'] == speed:
first = fighter1
second = '???'
third = '???'
last = '???'

In this case you can use sorted()
turn = 1
speeds = (fighter1['speed'], fighter2['speed'], pcfighter1['speed'], pcfighter2['speed'])
order = initiative(speeds)
for speed in sorted(order):
if fighter1['speed'] == speed:
first = fighter1
second = '???'
third = '???'
last = '???'

Related

Python nested dictionary iterate and create new dictionary

I have a python dictionary where I am iterating it and creating a new dictionary with some calculations. My current code is working fine but I want to know what are the other different ways to do it?
The logic is-
1. if the same `room` has multiple `rate` codes then append it to that room.
2. get the lowest price for every room type.
Existing Code:
datas = [
{"code": "A1KXDY", "room": "A1K", "rate": "XDX", "price": 10},
{"code": "B1KXDY", "room": "B1K", "rate": "XDX", "price": 20},
{"code": "C1KXDY", "room": "C1K", "rate": "XDX", "price": 30},
{"code": "A1KXDY", "room": "A1K", "rate": "XDY", "price": 5},
{"code": "B1KXDY", "room": "B1K", "rate": "XDY", "price": 10},
{"code": "C1KXDY", "room": "C1K", "rate": "XDY", "price": 40},
]
final_result = {}
for data in datas:
display_rate = data["price"]
if data["room"] in final_result:
existing_room = final_result[data["room"]]
existing_room["rate_codes"].append(data["rate"])
current_rate = existing_room["display_rate"]
if current_rate > display_rate:
existing_room["display_rate"] = display_rate
continue
room_data = {"display_rate": display_rate, "rate_codes": [data["rate"]]}
final_result[data["room"]] = room_data
print(final_result)
Expected Output:
{'A1K': {'display_rate': 5, 'rate_codes': ['XDX', 'XDY']}, 'B1K': {'display_rate': 10, 'rate_codes': ['XDX', 'XDY']}, 'C1K': {'display_rate': 30, 'rate_codes': ['XDX', 'XDY']}}
You can use pandas for this.
import pandas as pd
datas = [...]
df = pd.DataFrame(datas)
df = df.groupby('room', as_index=False).agg({'price': min, 'rate': list})
df.rename(columns={'price': 'display_rate', 'rate': 'rate_codes'}, inplace=True)
result = df.to_dict('records')
Output:
[{'room': 'A1K', 'display_rate': 5, 'rate_codes': ['XDX', 'XDY']},
{'room': 'B1K', 'display_rate': 10, 'rate_codes': ['XDX', 'XDY']},
{'room': 'C1K', 'display_rate': 30, 'rate_codes': ['XDX', 'XDY']}]
The output can further be treated to match the output you want for final_result.
I would say your solution is fine. What constitutes "more smartly" is subjective to a large extent anyway.
I suppose, if you were willing to accept a set of rate_codes in the final result instead of a list, you could get away with fairly few lines of code:
final_result = {}
for data in datas:
room_key = data["room"] # just for readability
final_result.setdefault(room_key, {
"display_rate": data["price"],
"rate_codes": {data["rate"]}
})
final_result[room_key]["display_rate"] = min(
final_result[room_key]["display_rate"],
data["price"]
)
final_result[room_key]["rate_codes"].add(data["rate"])
Using the dict.setdefault method does nothing to final_result if it already has the key room_key; otherwise it inserts it with the value of that new dictionary.
We can use the min function instead of explicitly comparing values.
And we use the fact that a set always has unique values, so we can just call its add method without needing to check if that rate code already exists.
The result:
{'A1K': {'display_rate': 5, 'rate_codes': {'XDX', 'XDY'}}, 'B1K': {'display_rate': 10, 'rate_codes': {'XDX', 'XDY'}}, 'C1K': {'display_rate': 30, 'rate_codes': {'XDX', 'XDY'}}}

python and Json - editing file

So, I want to change my info in json file from python, but I am having trouble.
my json file is just info that I want to edit later:
[
{
"codigo": 10,
"Nom_articulo": "jabon",
"valor": 2500,
"cantidad": 6,
"subtotal": 0,
"descuento": 0
},
{
"codigo": 20,
"Nom_articulo": "Crema",
"valor": 9800,
"cantidad": 4,
"subtotal": 0,
"descuento": 0
},
{
"codigo": 30,
"Nom_articulo": "Cepillo",
"valor": 6000,
"cantidad": 7,
"subtotal": 0,
"descuento": 0
},
{
"codigo": 40,
"Nom_articulo": "Servilletas",
"valor": 3000,
"cantidad": 2,
"subtotal": 0,
"descuento": 0
},
{
"codigo": 50,
"Nom_articulo": "Desodorante",
"valor": 5000,
"cantidad": 6,
"subtotal": 0,
"descuento": 0
}
]
I want to change the value of "subtotal" in all my dictionaries.
so basically what I did was:
for i in range(len(archivo_r)):
precio= archivo_r[i]["valor"]
cantidad=archivo_r[i]["cantidad"]
subtotal=precio*cantidad
print(archivo_r[i]["codigo"], " - " ,archivo_r[i]["Nom_articulo"], " = ", str(subtotal))
#almacenar mis subtotales en el archivo json
print("sbtotal" ,archivo_r[i]["subtotal"])
archivo_r[i]["subtotal"]=subtotal
#archivo_r[i]["subtotal"].append(subtotal)
#print(archivo_r)
write_json(**XXXXX**)
This part of the code:
archivo_r[i]["subtotal"]=subtotal does exactly what I need, but (and this could be very silly, but I am a little lost here) I do not know how to use that to re-write my json file. I mean, I have the function to write it.
def write_json(info, nombre_archivo="productos.json"):
with open(nombre_archivo, "w") as p:
json.dump(info, p)
I need to pass the information in write_json(**XXXXX**), but have been trying to storage my archivo_r[i]["subtotal"]=subtotal in a variable to pass it and other things, but nothing work. I know I am doing wrong but not sure how to solve it.
Once you're done processing the data, simply pass archivo_r to your write_json() function and you should be fine.
As an aside, you can iterate directly over the JSON objects like so:
for section in archivo_r:
precio = section["valor"]
...
You can then replace all instances of archivo_r[i] with section, or whatever you want to call the variable.

find time difference between previous and new data in collection using pymongo

I have list of dictionary data which is inserted in mongodb using pymongo
data =[{
"cam_name" : "cam1",
"stats" : [
{
"total" : 10,
"red" : 5,
"yellow" : 0,
"green" : 5,
"time_stamp" : datetime(2020,6,20,17,52,4,992000),
"image_path" : "image/19-06-2020/cam1/19-06-2020_17-52-16.jpg"
},
{
"total" : 10,
"red" : 5,
"yellow" : 0,
"green" : 5,
"time_stamp" : datetime(2020,6,20,17,52,27,992000),
"image_path" : "image/19-06-2020/cam1/19-06-2020_17-52-25.jpg"
},
{
"total" : 10,
"red" : 5,
"yellow" : 0,
"green" : 5,
"time_stamp" : datetime(2020,6,20,17,52,1,992000),
"image_path" : "image/19-06-2020/cam1/19-06-2020_17-52-25.jpg"
}]
},
{
"cam_name": "cam2",
"stats": [
{
"total": 10,
"red": 5,
"yellow": 0,
"green": 5,
"time_stamp": datetime(2020, 6, 20, 17, 52, 6, 992000),
"image_path": "image/19-06-2020/cam1/19-06-2020_17-52-16.jpg"
},
{
"total": 10,
"red": 5,
"yellow": 0,
"green": 5,
"time_stamp": datetime(2020, 6, 20, 17, 52, 59, 992000),
"image_path": "image/19-06-2020/cam1/19-06-2020_17-52-25.jpg"
},
{
"total": 10,
"red": 5,
"yellow": 0,
"green": 5,
"time_stamp": datetime(2020,6, 20, 17, 52, 4, 992000),
"image_path": "image/19-06-2020/cam1/19-06-2020_17-52-25.jpg"
}]
}
]
And after entering the data I am trying to find the difference between time between each element in list of dictionaries available for key ['stats']['time_stamp']
But I am not able to find out by using the approach of finding difference between the elements available in the list
from pymongo import MongoClient
from datetime import datetime
import json
import pandas as pd
from datetime import timedelta
myclient = MongoClient('localhost', 27017)
master_data = myclient['data_set']
cam_db = master_data['cam_table']
prev = None
for i,c in enumerate(data):
for k in c['stats']:
#print(k['time_stamp'])
if prev==None:
prev = k['time_stamp']
#print(prev)
else:
prev = k['time_stamp'] - prev
print(prev)
output:
0:00:23
2020-06-20 17:52:08.992000
-1 day, 23:59:56
2020-06-20 17:52:31.992000
0:00:00
after that, I am not able to find the perfect approach to use for find out the time difference
Note: I want to check whether time difference between every data available is less than 20 seconds or not
Suggestions will be really helpful

How do I copy values from one dictionary to a second dictionary with new keys?

I am trying to make weapons in my game exclusive to certain classes. I have an item database in form:
itemsList = {
1: {"name": "Padded Armor", "armor": 1, "value": 5, "class": "light"},
2: {"name": "Leather Armor", "armor": 2, "value": 10, "class": "light"},
3: {"name": "Studded Leather Armor", "armor": 3, "value": 25, "class": "light"},
...
19: {"name": "Dagger", "damage" : int(random.randrange(1, 4)), "value": 2, "Type": "Dagger"},
20: {"name": "Dagger + 1", "damage" : int(random.randrange(1, 4) + 1), "value": 200, "Type": "Dagger"},
21: {"name": "Dagger + 2", "damage" : int(random.randrange(1, 4) + 2), "value": 750, "Type": "Dagger"},
22: {"name": "Dagger + 3", "damage" : int(random.randrange(1, 4) + 3), "value": 2000, "Type": "Dagger"}
}
I am going to import, if a class can equip a certain weapon, to a new dictionary,
character.canEquipWeapon = {}
I would like to assign the name, damage, value, and type to a new set of keys in the dictionary, only, I would like to add only certain subsets (daggers, maces, swords) to certain classes.
I have tried
character.canEquipWeapon.update(itemsList[5])
and that just overwrites the dictionary with each new value. How do I go about doing this?
You could create a dict with usable items by class, so that for a given class, you have the list of the IDs it can equip as such :
classItem = {
'rogue' : [1,2,3,12,13,14,15],
'mage' : [13,15,16,18],
'soldier' : [1,2,3,4,5,6,7],
}
Then to get the list of items usable by the rogue for instance :
rogueItems = [v for k,v in itemsList.items() if k in classItem['rogue']]
Note that with python2 you'd have to use itemsList.iteritems() instead of itemsList.items()
How do you feel about making itemsList an array instead of a dict? Seems like you're using it as an array anyhow. That way, you could do something like
itemsList2 = [weapon for weapon in itemsList if weapon.type == "dagger"]
or if the weapon types are stored in, say, character.weaponTypes
itemsList2 = [weapon for weapon in itemsList if weapon.type in character.weaponTypes]

Get child dict values use Mongo Map/Reduce

I have a mongo collection, i want get total value of 'number_of_ad_clicks' by given sitename, timestamp and variant id. Because we have large data so it would be better use map/reduce. Could any guys give me any suggestion?
Here is my collection json format
{ "_id" : ObjectId( "4e3c280ecacbd1333b00f5ff" ),
"timestamp" : "20110805",
"variants" : { "94" : { "number_of_ad_clicks" : 41,
"number_of_search_keywords" : 9,
"total_duration" : 0,
"os" : { "os_2" : 2,
"os_1" : 1,
"os_0" : 0 },
"countries" : { "ge" : 6,
"ca" : 1,
"fr" : 8,
"uk" : 4,
"us" : 6 },
"screen_resolutions" : { "(320, 240)" : 1,
"(640, 480)" : 5,
"(1024, 960)" : 5,
"(1280, 768)" : 5 },
"widgets" : { "widget_1" : 1,
"widget_0" : 0 },
"languages" : { "ua_uk" : 8,
"ca_en" : 2,
"ca_fr" : 2,
"us_en" : 5 },
"search_keywords" : { "search_keyword_8" : 8,
"search_keyword_5" : 5,
"search_keyword_4" : 4,
"search_keyword_7" : 7,
"search_keyword_6" : 6,
"search_keyword_1" : 1,
"search_keyword_3" : 3,
"search_keyword_2" : 2 },
"number_of_pageviews" : 18,
"browsers" : { "browser_4" : 4,
"browser_0" : 0,
"browser_1" : 1,
"browser_2" : 2,
"browser_3" : 3 },
"keywords" : { "keyword_5" : 5,
"keyword_4" : 4,
"keyword_1" : 1,
"keyword_0" : 0,
"keyword_3" : 3,
"keyword_2" : 2 },
"number_of_keyword_clicks" : 83,
"number_of_visits" : 96 } },
"site_name" : "fonter.com",
"number_of_variants" : 1 }
Here is my try. but failed.
He is my try.
m = function() {
emit(this.query, {variants: this.variants});
}
r = function(key , vals) {
var clicks = 0 ;
for(var i = 0; i < vals.length(); i++){
clicks = vals[i]['number_of_ad_clicks'];
}
return clicks;
}
res = db.variant_daily_collection.mapReduce(m, r, {out : "myoutput", "query":{"site_name": 'fonter.com', 'timestamp': '20110805'}})
db.myoutput.find()
could somebody any suggestion?
Thank you very much, i try you solution but nothing return.
I invoke the mapreduce in the following, is there any thing wrong?
res = db.variant_daily_collection.mapReduce(map, reduce, {out : "myoutput", "query":{"site_name": 'facee.com', 'timestamp': '20110809', 'variant_id': '305'}})
db.myoutput.find()
The emit function emits both a key and a value.
If you are used to SQL think of key as your GROUP BY and value as your SUM(), AVG(), etc..
In your case you want to "group by": site_name, timestamp and variant id. It looks like you may have more than one variant, so you will need to loop through the variants, like this:
map = function() {
for(var i in variants){
var key = {};
key.timestamp = this.timestamp;
key.site_name = this.site_name;
key.variant_id = i; // that's the "94" string.
var value = {};
value.clicks = this.variants[i].number_of_ad_clicks;
emit(key, value);
}
}
The reduce function will get an array of values each one like this { clicks: 41 }. The function needs to return one object that looks the same.
So if you get values = [ {clicks:21}, {clicks:10}, {clicks:5} ] you must output {clicks:36}.
So you do something like this:
reduce = function(key , vals) {
var returnValue = { clicks: 0 }; // initializing to zero
for(var i = 0; i < vals.length(); i++){
returnValue.clicks += vals[i].clicks;
}
return returnValue;
}
Note that the value from map has the same shape as the return from reduce.

Categories

Resources