comparison multimerge.py @ 62:4891ed8d77d5

Implement nearest matching color search via cubic distance, and use it for finding best matching color from available event colors based on source calendar color.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 11 Jul 2016 13:37:26 +0300
parents 9fe4faa80687
children 6e38692e341f
comparison
equal deleted inserted replaced
61:9fe4faa80687 62:4891ed8d77d5
10 import os 10 import os
11 import sys 11 import sys
12 import signal 12 import signal
13 import re 13 import re
14 import codecs 14 import codecs
15 import math
15 #import time 16 #import time
16 #import datetime 17 #import datetime
17 18
18 import smtplib 19 import smtplib
19 from email.mime.text import MIMEText 20 from email.mime.text import MIMEText
130 for field in ev1: 131 for field in ev1:
131 if not field in gcm_no_compare_fields and ev1[field] != ev2[field]: 132 if not field in gcm_no_compare_fields and ev1[field] != ev2[field]:
132 return False 133 return False
133 return True 134 return True
134 135
136 class GCMColor():
137 def __init__(self, src = None):
138 if src == None:
139 self.r = self.g = self.b = 0
140 elif isinstance(src, basestring):
141 if len(src) == 6:
142 self.r = int(src[0:2], 16)
143 self.g = int(src[2:4], 16)
144 self.b = int(src[4:6], 16)
145 elif len(src) == 7 and src[0] == "#":
146 self.r = int(src[1:3], 16)
147 self.g = int(src[3:5], 16)
148 self.b = int(src[6:7], 16)
149 else:
150 gcm_fatal("Expected hex-triplet string for GCMColor() initializer: {0}".format(src))
151 elif isinstance(src, GCMColor):
152 self.r = src.r
153 self.g = src.g
154 self.b = src.b
155 else:
156 gcm_fatal("Invalid initializer for GCMColor() object.")
157
158 def delta(self, other):
159 ctmp = GCMColor()
160 ctmp.r = other.r - self.r
161 ctmp.g = other.g - self.g
162 ctmp.b = other.b - self.b
163 return ctmp
164
165 def dist(self, other):
166 ctmp = self.delta(other)
167 return math.sqrt(ctmp.r * ctmp.r + ctmp.g * ctmp.g + ctmp.b * ctmp.b)
168
169
170 def gcm_find_nearest_color(colors, cfind, maxdist):
171 c_fg = GCMColor(cfind["foreground"])
172 c_bg = GCMColor(cfind["background"])
173
174 bdist_fg = 99999999999
175 bdist_bg = 99999999999
176 best_fit = None
177 for id, col in colors.iteritems():
178 dist_fg = GCMColor(col["foreground"]).dist(c_fg)
179 dist_bg = GCMColor(col["background"]).dist(c_bg)
180 if dist_fg <= bdist_fg and dist_bg <= bdist_bg:
181 best_fit = id
182 bdist_fg = dist_fg
183 bdist_bg = dist_bg
184
185 if bdist_fg <= maxdist and bdist_bg <= maxdist:
186 return best_fit
187 else:
188 return None
189
135 190
136 ## 191 ##
137 ## Class for handling configuration / settings 192 ## Class for handling configuration / settings
138 ## 193 ##
139 class GCMSettings(dict): 194 class GCMSettings(dict):
406 ## Check if we have destination calendar ID 461 ## Check if we have destination calendar ID
407 if not dst_calendar: 462 if not dst_calendar:
408 gcm_fatal(u"Could not find target/destination calendar ID for '"+ cfg.dest_name +"'.") 463 gcm_fatal(u"Could not find target/destination calendar ID for '"+ cfg.dest_name +"'.")
409 else: 464 else:
410 gcm_debug(u"Target calendar '{0}' id {1}.".format(dst_calendar["summary"], dst_calendar["id"])) 465 gcm_debug(u"Target calendar '{0}' id {1}.".format(dst_calendar["summary"], dst_calendar["id"]))
466
467
468 ## Fetch colors
469 try:
470 colors = service.colors().get().execute()
471 except Exception as e:
472 gcm_fatal("Failed to fetch calendar color settings:\n\n{0}".format(str(e)))
411 473
412 474
413 ## Now, we fetch and collect events 475 ## Now, we fetch and collect events
414 gcm_debug(u"Fetching calendar events .. ") 476 gcm_debug(u"Fetching calendar events .. ")
415 src_events = [] 477 src_events = []
421 singleEvents=True, 483 singleEvents=True,
422 showDeleted=False, 484 showDeleted=False,
423 # orderBy="startTime", 485 # orderBy="startTime",
424 ).execute() 486 ).execute()
425 487
488 c_found = None
489 if "colorId" in calendar and calendar["colorId"] in colors["calendar"]:
490 gcm_debug("Calendar color: {0}".format(colors["calendar"][calendar["colorId"]]))
491 c_found = gcm_find_nearest_color(colors["event"], colors["calendar"][calendar["colorId"]], 100)
492 if c_found:
493 gcm_debug("Found nearest event color ID: {0}, {1}".format(c_found, colors["event"][c_found]))
494 else:
495 gcm_debug("No matching event color found!")
496
426 # Add events, if any, to main list 497 # Add events, if any, to main list
427 events = gcm_generate_ids(result.get("items", []), calendar["id"]) 498 events = gcm_generate_ids(result.get("items", []), calendar["id"])
428 if events: 499 if events:
429 for event in events: 500 for event in events:
430 if "colorId" in calendar: 501 if c_found != None:
431 event["colorId"] = calendar["colorId"] 502 event["colorId"] = c_found
432 event["summary"] = u"[{1}] {0}".format(event["summary"], calendar["gcm_id"]) 503 event["summary"] = u"[{1}] {0}".format(event["summary"], calendar["gcm_id"])
433 src_events.extend(events) 504 src_events.extend(events)
434 if cfg.debug: 505 if cfg.debug:
435 gcm_dump_events(events) 506 gcm_dump_events(events)
436 507