def download_poster(self, size, destination, choose): ''' download associated movie poster size: w92, w154, w185, w342, w500, or original see http://help.themoviedb.org/kb/api/configuration name: name to save it as ''' if choose: print 'Creating image selection palette(s)...' posters = _get_all_posters(self.posters, size) poster_qty = len(posters) if poster_qty <= 1: print 'No palette created,', poster_qty, 'image(s) available' return download_file(self.poster.geturl(size), destination) draw_mosaic(posters) choice = get_input('Choose an image to use for movie poster: ', '(^$)|(^(Q|q)$)|(^\d{1,2}$)', 1, poster_qty) if re.match('^(Q|q)$', choice): exit() if not choice: poster_url = self.poster.geturl(size) else: poster_url = self.posters[int(choice)-1].geturl(size) else: poster_url = self.poster.geturl(size) image = download_file(poster_url, destination) if destination == 'temp': return image is_reduced = reduce_size(destination, 90) if is_reduced: notify('warning', 'image quality reduced and useless data removed for ' + os.path.splitext(os.path.basename(destination))[0], sys.stderr)
def main(): args = init_parser() # if user didn't specify a tv path or movie path, tell them if not args.movie_paths and not args.tv_paths \ and not args.media_library: print '-m/-t/-L option is necessary.' # repair library if requested if args.media_library and not args.movie_paths and not args.tv_paths: if not os.path.isfile(args.media_library): notify('error', 'media library file does not exist') exit() modify_db(args.media_library, args.show, None, True) # process all the movie paths for path in args.movie_paths: path = parse_path(path) v=process_movies(path, args.thumbnails, args.assume, args.interactive, args.show, args.force_overwrite, args.language, args.country, int(args.max_results), args.choose_image) if args.media_library and v: modify_db(args.media_library, args.show, v) # process all the tv series paths if not args.language in 'en sv no da fi nl de it es fr pl hu el ' \ 'tr ru he ja pt zh cs sl hr ko': notify('error', 'invalid language') exit() for path in args.tv_paths: path = parse_path(path) v=process_tv(path, args.interactive, args.show, args.force_overwrite, args.language, args.choose_image, int(args.max_results), args.dvd_ordering) if args.media_library: modify_db(args.media_library, args.show, v)
def estimate_suicide_burn(self): vessel = self.vessel orbit = vessel.orbit body = orbit.body buffer = 100 ut = self.ut() max_height = self.sample_surface_height() * 1.1 r = body.equatorial_radius + max_height + buffer d = self.surface_altitude() - buffer mu = body.gravitational_parameter g = mu / (r * r) v = self.speed() # https://en.wikipedia.org/wiki/Equations_for_a_falling_body delta_v = v + math.sqrt(2 * mu * (1 / r - 1 / (r + d))) delta_t = self.burn_time(delta_v, against_g=g) #TTI = 2 * d / (delta_v + v) #g_avg = 0.5 * g + 0.5 * mu / ((d+r)*(d+r)) #TTI = (v + math.sqrt(v*v + 2*g_avg*d)) / g_avg #TTI = (delta_v - v) / g_avg anom = orbit.true_anomaly_at_radius(r + buffer) ut = min(orbit.ut_at_true_anomaly(anom), orbit.ut_at_true_anomaly(-anom)) notify(ut - self.ut(), delta_v, delta_t) return ut, delta_v, delta_t
def open(self, email, password): try: # ページ読み込み self.driver.implicitly_wait(10) self.driver.get('chrome-extension://%s/index.html' % self.APP_ID) # メールアドレス elem = self.driver.find_element_by_id('line_login_email') elem.send_keys(email) # パスワード elem = self.driver.find_element_by_id('line_login_pwd') elem.send_keys(password) # ログイン elem = self.driver.find_element_by_id('login_btn') elem.click() # 本人確認コードを通知 elem = self.driver.find_element_by_xpath( "//div[@class='mdCMN01Code']") notify('Enter %s to Mobile LINE' % elem.text, time=20000) # トーク self.driver.implicitly_wait(60) elem = self.driver.find_element_by_id('_chat_list_body') # トーク一覧を作成 chatlist = [] elems = elem.find_elements_by_xpath("./li") for elem in elems: title = elem.get_attribute('title') chatlist.append(title.encode('utf-8')) # 設定ファイルを更新 Settings().update(chatlist) return 1 except Exception as e: log(traceback.format_exc()) notify('Login failed', error=True, time=3000) self.close() return 0
def warp_to_soi(self): vessel = self.vessel orbit = vessel.orbit ksc = self.conn.space_center while orbit.time_to_soi_change < orbit.time_to_periapsis: notify('Warping to next sphere of influence...') ksc.warp_to(ksc.ut + orbit.time_to_soi_change + 1) orbit = vessel.orbit
def _save_poster(location, destination, basename, max_size): # If there is no art, carry on if not location: notify('warning', 'no image available for ' + basename) return download_file(location, destination) is_reduced = reduce_size(destination, max_size) if is_reduced: notify('warning', 'image quality reduced and useless data removed for ' + basename, sys.stderr)
def execute(self): self.warp_to_soi() self.connect_streams() if self.situation() == self.conn.space_center.VesselSituation.landed: return vessel = self.vessel control = vessel.control vessel.control.solar_panels = False if self.periapsis_altitude() > 0: self.lower_periapsis() if vessel.orbit.body.has_atmosphere: self.reentry_burn() if self.surface_altitude() > 20000: self.slow_down(vessel) start = time.perf_counter() notify('scanning for landing site...') target = self.find_safe_landing() notify(f'scan took {time.perf_counter() - start}') notify(f'landing at {target}') self.controlled_descent(target) vessel.auto_pilot.disengage() control.sas = True control.sas_mode = control.sas_mode.stability_assist notify('Landed?')
def submit(self, message): try: # メッセージを送信 self.driver.implicitly_wait(10) elem = self.driver.find_element_by_id('_chat_room_input') elem.click() elem.send_keys(message) elem.send_keys(Keys.ENTER) return 1 except: log(traceback.format_exc()) notify('Submission failed', error=True, time=3000) self.close() return 0
def select(self, talk): try: # 指定したトークを選択 self.driver.implicitly_wait(10) elem = self.driver.find_element_by_id('_chat_list_body') if talk == 'default': elem2 = elem.find_element_by_xpath("./li[@title!='']") else: elem2 = elem.find_element_by_xpath("./li[@title='%s']" % talk.decode('utf-8')) elem2.click() return 1 except Exception as e: log(traceback.format_exc()) notify('Selection failed', error=True, time=3000) self.close() return 0
def toggle_notifications(): """Turn notifications on/off.""" name = 'SHOW_NOTIFICATIONS' is_active = boolvar(name) what = 'on' value = '1' if is_active: what = 'off' value = '0' msg = 'Turned notifications ' + what savevar(name, value) log.info(msg) notify(msg) run_trigger('config')
def toggle_locale(loc): """Toggle a locale on or off.""" active = wf.settings.get('locales', []) is_active = loc in active if is_active: msg = u'Deactivated locale {}'.format(ALL_LOCALES.get(loc)) active.remove(loc) wf.settings['locales'] = active else: msg = u'Activated locale {}'.format(ALL_LOCALES.get(loc)) active.append(loc) wf.settings['locales'] = active log.info(msg) notify(msg) run_trigger('locales')
def slow_down(self, vessel): notify('Slowing down...') vessel = self.vessel control = vessel.control rf = vessel.orbit.body.reference_frame flight = vessel.flight(rf) _surface_velocity = self.conn.add_stream(getattr, flight, 'velocity') surface_velocity = lambda: -np.array(_surface_velocity()) ap = vessel.auto_pilot ap.engage() ap.reference_frame = rf ap.target_direction = surface_velocity() ap.wait() g = self.surface_gravity ut, delta_v, delta_t = self.estimate_suicide_burn() self.conn.space_center.warp_to(ut - 0.5 * delta_t) control.throttle = 1.0 effective_twr = self.TWR() - self.surface_gravity notify( f'surface_altitude:{self.surface_altitude()}, vertical_speed:{self.vertical_speed()}, effective_twr:{effective_twr}' ) while -self.vertical_speed() > 10 * effective_twr: ap.target_direction = surface_velocity() wait() control.throttle = 0.0 notify( f'surface_altitude:{self.surface_altitude()}, vertical_speed:{self.vertical_speed()}' )
def edited(self, id, key, s, day, ch, duplicate): key = re.sub(r'(^\s+|\s+$)','',key) if id=='': for elem in self.search: if elem['key'] == key: notify('Keyword edit failed (Keyword exists)', error=True) return elem = {} elem['key'] = key elem['s'] = s elem['day'] = day elem['ch'] = ch elem['duplicate'] = duplicate self.search.append(elem) # キーワードを表示 xbmc.executebuiltin("Container.Update(%s?action=showKeywords)" % (sys.argv[0])) else: if self.search[int(id)]['key'] == key: pass else: for elem in self.search: if elem['key'] == key: notify('Keyword edit failed (Keyword exists)', error=True) return elem = self.search[int(id)] elem['key'] = key elem['s'] = s elem['day'] = day elem['ch'] = ch elem['duplicate'] = duplicate # 再表示 xbmc.executebuiltin("Container.Refresh") # キーワード順にソート self.search = sorted(self.search, key=lambda item: item['key']) # 変更した設定を書き込む self.write()
def execute(self): orbit = self.vessel.orbit if abs(orbit.apoapsis - orbit.periapsis) < 1e4 and orbit.periapsis_altitude > orbit.body.atmosphere_depth: return notify("Circularizing...") self.initial_apoapsis = self.apoapsis() control = self.vessel.control control.throttle = 0.0 radius = max(self.apoapsis(), self.periapsis()) delta_v = self.circularization_delta_v(radius) burn_time = self.burn_time(delta_v) ut = self.ut() apoapsis_ut = ut + min(orbit.time_to_apoapsis, orbit.time_to_periapsis) eccentricity = self.eccentricity() notify(f"delta_v: {delta_v}") notify(f"burn_time: {burn_time}") notify(f"initial_eccentricity: {eccentricity}") control.add_node(apoapsis_ut, prograde=delta_v) self.execute_next_node() notify(f"final_eccentricity: {self.eccentricity()}")
def __get_series_info(self, tvdbId, language): ''' returns information on a series with the id <tvdbId> ''' try: return longsearch.searchForLongSeries(tvdbId, language) except urllib2.HTTPError as e: if e.code == 404: notify('http 404 error', language + ' probably is invalid') elif e.code == 504: notify('http 504 error', 'thetvdb.com is not responding') elif e.code == 503: notify('http 503 error', 'thetvdb.com is busy, try later') exit()
def save_xmltv(): try: common.dbg_log('functions::save_xmltv', 'enter_function') common.notify(common.__scriptname__, common.Lang(33001), 'IconInfo') pDialog = xbmcgui.DialogProgressBG() pDialog.create(common.Lang(33004), '') prs = parservsetv.parser(pDialog) prs.get_content() prs.save_xml() pDialog.close() common.notify(common.__scriptname__, common.Lang(33002), 'IconInfo') xbmcaddon.Addon(common.__scriptid__).setSetting("last_update",datetime.datetime.now().strftime('%Y%m%d')) if common.execute_script == 'true': common.dbg_log('functions::save_xmltv', 'execute script - ' + common.script_patch) common.execute(common.script_patch) common.dbg_log('functions::save_xmltv', 'exit_function') except Exception, e: common.notify(common.__scriptname__, common.Lang(33003), 'IconError') common.dbg_log('functions::save_xmltv', 'ERROR: (' + repr(e) + ')', common.logErorr)
def process_movies(path, thumbnails, assume, interactive, show, force_overwrite, language, country, max_results, choose_image): successful = [] # configurations for tmdb api tmdb3.set_key('ae90cf3b0ab5da570880728198701ce0') tmdb3.set_cache('null') # set language and country if (not language) and (not country): tmdb3.set_locale(fallthrough=True) else: if language: tmdb3.set_locale(language=language, fallthrough=True) if country: tmdb3.set_locale(country=country, fallthrough=True) if 'debug' in show: notify('processing', path) notify('locale', str(tmdb3.get_locale())) if not os.path.isdir(path): notify('warning', '\'' + path + '\' is not a directory') return # process each file in path for f in os.listdir(path): # check if file is in a format that wdtv supports if not re.search('(\.avi|\.vob|\.iso|\.wmv|\.mkv|\.m4v|\.mov|\.dat|' '\.tp|\.ts|\.m2t|\.m2ts|\.flv|.mp4)$', f): continue # create a new LocalVideo object using the movie file videofile = LocalVideo(f) if (os.path.isfile(path + '/' + videofile.basename + '.metathumb') and os.path.isfile(path + '/' + videofile.basename + '.xml') and (not force_overwrite)): # metathumb and xml already exists for this movie if 'exists' in show or 'all' in show: notify(videofile.basename, 'poster and metadata already exist') continue # find a matching title from tmdb try: videofile.get_match(assume) except common.NonzeroMatchlistNoMatches as e: if 'error' in show or 'all' in show: print e except common.ZeroMatchlist as e: if 'error' in show or 'all' in show: print e if not videofile.tmdb_data: if not interactive: continue videofile.tmdb_data = manually_search_movie(videofile.basename, videofile.uni_title, max_results) if not videofile.tmdb_data: if 'error' in show or 'all' in show: notify(videofile.basename, 'not found') continue if 'ok' in show or 'all' in show: if videofile.matched_method == 'assumed': notify(videofile.basename, 'assuming matches ' + videofile.tmdb_data.full_title()) else: notify(videofile.basename, 'matches ' + videofile.tmdb_data.full_title()) # deal with poster if (os.path.isfile(path + '/' + videofile.basename + '.metathumb') and not force_overwrite): if 'exists' in show or 'all' in show: notify(videofile.basename, 'poster already exists') else: # if there's any posters available, download w185 size # preferably. otherwise, get the smallest available. if videofile.tmdb_data.poster: if 'w342' in videofile.tmdb_data.poster.sizes(): videofile.tmdb_data.download_poster('w185', path + '/' + videofile.basename + '.metathumb', choose_image) else: videofile.tmdb_data.download_poster( videofile.tmdb_data.poster.sizes()[0], path + '/' + videofile.basename + '.metathumb', choose_image) elif 'error' in show or 'all' in show: notify(videofile.basename, 'no poster available') # deal with metadata if (os.path.isfile(path + '/' + videofile.basename + '.xml') and not force_overwrite): if 'exists' in show or 'all' in show: notify(videofile.basename, 'metadata already exists') else: videofile.tmdb_data.write_metadata( path + '/' + videofile.basename + '.xml', thumbnails) successful.append(path + '/' + videofile.basename + videofile.ext) return successful
def write_movie(mov, destination, thumbnails): ''' write meta information to a file mov: tmdb3.Movie object to get info from destination: destination of file to write thumbnails: boolean describing whether to include thumbnail URLs or not this is included because on the WDTV if thumbnail URLs are known, it will try and use those before the local .metathumb files which slows movie browsing down ''' try: xml = list() xml.append('<?xml version="1.0"?>' '<!DOCTYPE note [' '<!ELEMENT details (id, imdb_id, title, mpaa, year, runtime, ' 'rating, trailer, genre, studio, plot, ' 'overview, director, actor, thumbnail, ' 'backdrop)>' '<!ELEMENT id (#PCDATA)>' '<!ELEMENT imdb_id (#PCDATA)>' '<!ELEMENT title (#PCDATA)>' '<!ELEMENT mpaa (#PCDATA)>' '<!ELEMENT year (#PCDATA)>' '<!ELEMENT runtime (#PCDATA)>' '<!ELEMENT rating (#PCDATA)>' '<!ELEMENT trailer (#PCDATA)>' '<!ELEMENT genre (#PCDATA)>' '<!ELEMENT studio (#PCDATA)>' '<!ELEMENT plot (#PCDATA)>' '<!ELEMENT overview (#PCDATA)>' '<!ELEMENT director (#PCDATA)>' '<!ELEMENT actor (#PCDATA)>' '<!ELEMENT thumbnail (#PCDATA)>' '<!ELEMENT backdrop (#PCDATA)>' ']>') xml.append('<details>') xml.append(' <id>' + unicode(mov.id) + '</id>') xml.append(' <imdb_id>' + unicode(mov.imdb) + '</imdb_id>') xml.append(' <title>' + mov.title + '</title>') if 'US' in mov.releases: xml.append(' <mpaa>' + mov.releases['US'].certification + '</mpaa>') xml.append(' <year>' + unicode(mov.releasedate) + '</year>') xml.append(' <runtime>' + unicode(mov.runtime) + '</runtime>') xml.append(' <rating>' + unicode(mov.userrating) + '</rating>') for trailer in mov.youtube_trailers: xml.append(' <trailer>' + trailer.geturl() + '</trailer>') for trailer in mov.apple_trailers: #best_quality = trailer.sizes()[len(trailer.sizes()) - 1] #xml += '<trailer>' + trailer.geturl(best_quality) + '</trailer>' if '480p' in trailer.sizes(): xml.append(' <trailer>' + trailer.geturl('480p') + '</trailer>') for genre in mov.genres: xml.append(' <genre>' + genre.name + '</genre>') for studio in mov.studios: xml.append(' <studio>' + studio.name + '</studio>') xml.append(' <plot>' + mov.overview + '</plot>') xml.append(' <overview>' + mov.overview + '</overview>') for member in mov.crew: if member.job.lower() == 'director': xml.append(' <director>' + member.name + '</director>') for actor in mov.cast: xml.append(' <actor>\n' ' <name>' + actor.name + '</name>\n' ' <role>' + actor.character + '</role>\n' ' </actor>') if thumbnails: for poster in mov.posters: xml.append(' <thumbnail>' + poster.geturl('w185') + '</thumbnail>') for backdrop in mov.backdrops: xml.append(' <backdrop>' + backdrop.geturl('w780') + '</backdrop>') xml.append('</details>') f = codecs.open(destination, encoding='utf-8', mode='w') for line in xml: # wdtv wants malformed xml # it does not change '&' to '&', so we must create bad xml line = line.replace(u'&', u'&') f.write(unicode(line) + u'\n') f.close() except UnicodeEncodeError: notify('warning', 'bad unicode', sys.stderr)
def execute(self): ksc = self.conn.space_center vessel = self.vessel vessel.control.rcs = True rf = vessel.surface_reference_frame # x: up, y: north, z: east ap = vessel.auto_pilot ap.engage() ap.reference_frame = rf body = vessel.orbit.body surface_gravity = body.surface_gravity tick = 0.01 r = body.equatorial_radius degrees_per_meter = 180 / r / math.pi lat0 = self.latitude() + 50 * degrees_per_meter lat1 = lat0 + 10 * degrees_per_meter lon0 = self.longitude() lon1 = lon0 + 20 * degrees_per_meter target = lambda: None if not self.TWR(): vessel.control.activate_next_stage() def create_lateral_control(): Kp = 0.2 Kd = 3.0 * Kp lateral_acc = 0.5 * surface_gravity control = CascadeControl( PID( Kp=Kp, Kd=Kd, sample_time=tick, ), PID( Kp=1.0, Kd=0.0, output_limits=(-lateral_acc, lateral_acc), sample_time=tick, )) control.controls[0] = lambda *x: 0 return control controllers = [ PID(1.0, 0.0, 1.5), # up/down create_lateral_control(), # N/S create_lateral_control(), # E/W ] error = [[], [], []] def update_throttle(): delta_h = target.altitude - self.surface_altitude() twr = self.TWR() err = delta_h acc = surface_gravity + controllers[0](-err) throttle = acc / twr error[0].append(err) return throttle def force_vector(): p = -np.array(target.pointer) v = np.array(target.relative_velocity) scale = min(1.0, max(target.distance, 2.0 * target.speed)) scale = 1.0 vec = np.array([ surface_gravity, scale * controllers[1](p[1], v[1]), scale * controllers[2](p[2], v[2]) ]) error[1].append(ap.error) error[2].append(v[1]) return vec target.altitude = 50.0 target.latitude = self.latitude() target.longitude = self.longitude() while vessel.met < 8.0: vessel.control.throttle = update_throttle() ap.target_direction = (1, 0, 0) wait(tick) while not self.abort(): if self.brakes(): target.altitude = 100.0 target.latitude = lat1 target.longitude = lon1 else: target.altitude = 50 target.latitude = lat0 target.longitude = lon0 target.position = body.position_at_altitude( target.latitude, target.longitude, self.mean_altitude(), body.reference_frame) target.reference_frame = body.reference_frame target.pointer = ksc.transform_position(target.position, target.reference_frame, rf) target.distance = np.linalg.norm(target.pointer) target.relative_velocity = -np.array( ksc.transform_velocity(target.position, (0, 0, 0), target.reference_frame, rf)) target.speed = np.linalg.norm(target.relative_velocity) notify(target.distance, target.speed) F = force_vector() ap.target_direction = F scaled_force = np.linalg.norm(F) / surface_gravity vessel.control.throttle = update_throttle() * scaled_force wait(tick) vessel.control.throttle = 0 err1 = np.array(error[1]) err2 = np.array(error[2]) t = np.arange(len(err1)) plt.plot(t, np.zeros_like(t), label='zero') plt.plot(t, np.log(np.abs(err1) + 1.0), label='log err1') plt.plot(t, err1, label='raw err1') plt.plot(t, np.log(np.abs(err2) + 1.0), label='log err2') plt.plot(t, err2, label='raw err2') plt.xlabel('time') plt.ylabel('error') plt.legend() plt.show() wait()
def watch(self): try: # メッセージ messages = [] self.driver.implicitly_wait(10) elems = self.driver.find_elements_by_xpath( "//div[@class='mdRGT07Msg mdRGT07Text' or @class='MdRGT10Notice mdRGT07Other mdRGT10Date']" ) for elem in elems: date = elem.get_attribute('data-local-id') if date: # 日付 d = datetime.datetime.fromtimestamp(int(date) / 1000) else: # メッセージ elem1 = elem.find_element_by_xpath( ".//span[@class='mdRGT07MsgTextInner']") msg = elem1.text.replace('\n', ' ').encode('utf-8') # 時刻 elem2 = elem.find_element_by_xpath( ".//p[@class='mdRGT07Date']") match = re.match(r'(AM|PM) (1?[0-9])\:([0-9][0-9])', elem2.text) hour = int(match.group(2)) minute = int(match.group(3)) if match.group(1) == 'PM': hour += 12 # 親エレメント elem3 = elem1.find_element_by_xpath("../../../..") cls = elem3.get_attribute('class') if cls == 'MdRGT07Cont mdRGT07Own': ttl = '自分' filepath = '' elif cls == 'MdRGT07Cont mdRGT07Other': ttl = elem3.find_element_by_xpath( "./div[@class='mdRGT07Body']/div[@class='mdRGT07Ttl']" ).get_attribute('textContent').encode('utf-8') img = elem3.find_element_by_xpath( "./div[@class='mdRGT07Img']/img").get_attribute( 'src').encode('utf-8') filepath = self.cache.path( hashlib.md5(ttl).hexdigest()) self.__savebinary(img, filepath) else: ttl = '' filepath = '' # リストに格納 message = { 'year': d.year, 'month': d.month, 'day': d.day, 'hour': hour, 'minute': minute, 'img': filepath, 'ttl': ttl, 'msg': msg } messages.append(message) return messages except Exception as e: log(traceback.format_exc()) notify('Extraction failed', error=True, time=3000) self.close() return 0
def modify_db(db_file, show, videos, repair=False): wdtv_dir = os.path.dirname(os.path.dirname(db_file)) conn = sqlite3.connect(db_file) c = conn.cursor() mlib_name = c.execute("SELECT name FROM folder WHERE filepath = './'").fetchone()[0] if 'debug' in show: notify('modifying media library', mlib_name) if not repair: broken = [ os.path.split(video) + ('new',) for video in videos ] else: broken = c.execute('''SELECT filepath, name, id FROM video WHERE title = name''').fetchall() for b in broken: b_filepath = b[0] b_name = b[1] b_id = b[2] b_fullpath = b_filepath + '/' + b_name b_fullpath_real = b_fullpath.replace('./' + mlib_name, wdtv_dir) b_dirname, b_filename = os.path.split(b_fullpath_real) b_basename, b_ext = os.path.splitext(b_filename) b_xml = (b_dirname + '/' + b_basename + '.xml') if not os.path.isfile(b_xml): if 'error' in show or 'all' in show: notify(os.path.basename(b_fullpath_real) + ' (' + str(b_id) + ')', 'could not repair record in media library, no matching xml') continue # xml will be malformed because wdtv wants it that way # now we make it compatible with ElementTree by replacing all the # '&'s with '&' tags with open(b_xml, 'r') as f: xml_contents = f.read() xml_contents = xml_contents.replace('&', '&') tree = ET.fromstring(xml_contents) director = tree.find('director') actors = tree.findall('actor/name') if director is not None: director = director.text else: director = '' if actors is not None: actors = [actor.text for actor in actors] actor = ' / '.join(actors) else: actor = '' if b_id == 'new': c.execute('SELECT * FROM video WHERE filepath = ? AND name = ?', (b_filepath.replace(wdtv_dir, './' + mlib_name), b_name)) record_exists = c.fetchall() if record_exists: if 'exists' in show or 'all' in show: notify(b_basename, 'record exists, not adding to db') continue c.execute('SELECT id FROM video ORDER BY id DESC LIMIT 1') rec_id = c.fetchone()[0] + 1 _, ino, _, _, _, _, size, _, mtime, ctime = os.stat(b_fullpath_real) mtime_date = time.strftime('%Y/%m/%d', time.gmtime(mtime)) season_name = episode_num = None series_name = tree.find('series_name') if series_name is not None: series_name = series_name.text season_num = tree.find('season_number').text season_name = 'Season %d' % (int(season_num)) episode_num = tree.find('episode_number').text c.execute('INSERT INTO video VALUES (' + ','.join(35*'?') + ')', (rec_id, 0, b_filename, b_filepath.replace(wdtv_dir, mlib_name), tree.find('title').text, tree.find('genre').text, mtime_date, season_name, series_name, episode_num, 0, size, ino, 0, 0, 0, mtime, ctime, 0, 0, 0, '', 0, 0, 0, 0, 0, -1, -1, 'Unknown', director, actor, '', '', '')) else: c.execute('''UPDATE video SET title = ?, genre = ?, director = ?, actor = ? WHERE name = ? AND filepath = ?''', (tree.find('title').text, tree.find('genre').text, director, actor, b[1], b[0] )) if tree.find('series_name') is not None: c.execute('''UPDATE video SET series_name = ?, season_name = ?, episode_num = ? WHERE name = ? AND filepath = ?''', (tree.find('series_name').text, 'Season %d' % (int(tree.find('season_number').text)), tree.find('episode_number').text, b[1], b[0])) conn.commit() if 'ok' in show or 'all' in show: notify(b_basename + ' (' + str(b_id) + ')', 'successfully repaired/added record') #print tree.find('id').text conn.close()
def write_tvshow(series, episode, destination, use_dvdorder): try: if use_dvdorder: season_num = episode.dvd_seasonNumber # dvd_episodeNumber is a decimal number so it can deal with episodes # aired as multiple episodes but combined on the dvd as one episode if float(episode.dvd_episodeNumber).is_integer(): episode_num = int(float(episode.dvd_episodeNumber)) else: episode_num = episode.dvd_episodeNumber else: season_num = episode.seasonNumber episode_num = episode.episodeNumber season_num = str(season_num) episode_num = str(episode_num) xml = list() xml.append('<?xml version="1.0"?>' '<!DOCTYPE note [' '<!ELEMENT details (id, title, series_name, episode_name, ' 'season_number, episode_number, ' 'firstaired, genre, runtime, director, ' 'actor, overview)>' '<!ELEMENT id (#PCDATA)>' '<!ELEMENT title (#PCDATA)>' '<!ELEMENT series_name (#PCDATA)>' '<!ELEMENT episode_name (#PCDATA)>' '<!ELEMENT season_number (#PCDATA)>' '<!ELEMENT episode_number (#PCDATA)>' '<!ELEMENT firstaired (#PCDATA)>' '<!ELEMENT genre (#PCDATA)>' '<!ELEMENT runtime (#PCDATA)>' '<!ELEMENT director (#PCDATA)>' '<!ELEMENT actor (#PCDATA)>' '<!ELEMENT overview (#PCDATA)>' ']>') xml.append('<details>') xml.append(' <id>' + unicode(episode.tvdbId) + '</id>') #title = '%s: S%sE%s %s' % (series.name, episode.seasonNumber.zfill(2), # episode.episodeNumber.zfill(2), episode.name) title = '%s%s: %s' % (season_num, episode_num.zfill(2), episode.name) xml.append(' <title>' + unicode(title) + '</title>') xml.append(' <series_name>' + unicode(series.name) + '</series_name>') xml.append(' <episode_name>' + unicode(episode.name) + '</episode_name>') xml.append(' <season_number>' + season_num + '</season_number>') xml.append(' <episode_number>' + episode_num + '</episode_number>') xml.append(' <firstaired>' + unicode(episode.firstAired) + '</firstaired>') # tv view does not give each genre its own item # use series name as genre to make genre filter less muddy xml.append(' <genre>' + unicode(series.name) + '</genre>') xml.append(' <runtime>' + 'N/A' + '</runtime>') xml.append(' <director>' + '/'.join(episode.director) + '</director>') # tv view does not give each actor their own item xml.append(' <actor>' + '/'.join(actor.name for actor in series.actors) + '</actor>') overview = ' <overview>' if use_dvdorder: overview = overview + 'Aired as ' + episode.seasonNumber + episode.episodeNumber.zfill(2) + '. ' elif episode.dvd_episodeNumber and episode.dvd_seasonNumber: if float(episode.dvd_episodeNumber).is_integer(): ep_on_dvd = str(int(float(episode.dvd_episodeNumber))).zfill(2) else: ep_on_dvd = episode.dvd_episodeNumber.zfill(4) overview = overview + 'On DVD as ' + episode.dvd_seasonNumber + ep_on_dvd + '. ' # overview is a list for some reason if len(episode.overview) > 0: overview = overview + episode.overview[0] xml.append(overview + '</overview>') xml.append('</details>') f = codecs.open(destination, encoding='utf-8', mode='w') for line in xml: # wdtv wants malformed xml # it does not change '&' to '&', so we must create bad xml line = line.replace(u'&', u'&') f.write(unicode(line) + u'\n') f.close() except UnicodeEncodeError: notify('warning', 'bad unicode', sys.stderr)
def controlled_descent(self, target=None): LANDED = self.conn.space_center.VesselSituation.landed SPLASHED = self.conn.space_center.VesselSituation.splashed vessel = self.vessel control = vessel.control control.trottle = 0 control.brakes = True control.gear = True control.lights = True control.solar_panels = False control.sas = False lat, lon = target # rf = vessel.surface_reference_frame rf = vessel.orbit.body.reference_frame flight = vessel.flight(rf) _pos = self.conn.add_stream(getattr, flight, 'center_of_mass') pos = lambda: np.array(_pos()) target_pos = lambda: np.array( vessel.orbit.body.surface_position(lat, lon, rf)) _surface_velocity = self.conn.add_stream(getattr, flight, 'velocity') surface_velocity = lambda: -np.array(_surface_velocity()) ap = vessel.auto_pilot ap.engage() ap.reference_frame = rf ap.target_direction = surface_velocity() landing_speed = 0.5 v_target = lambda: 0.2 * self.surface_altitude() + landing_speed base_throttle = lambda: self.surface_gravity / self.TWR() effective_twr = self.TWR() - self.surface_gravity notify('Waiting for landing burn...') while self.surface_altitude( ) > self.stopping_distance() + 2.0 * wait.interval * self.speed(): ap.target_direction = surface_velocity() wait() control.throttle = 1.0 notify('Landing burn!') notify(f'altitude: {self.surface_altitude()}') while self.speed() > 5 * effective_twr: d = surface_velocity() ap.target_direction = d / np.linalg.norm(d) wait() notify(f'effective_twr: {effective_twr}') pid = PID(0.2, 0.0, 0.0, sample_time=wait.interval, output_limits=(-1.0, 1.0)) notify('Entering controlled descent...') while self.situation() not in [LANDED, SPLASHED]: altitude = self.surface_altitude() base = base_throttle() target = v_target() actual = -self.vertical_speed() pid_input = target - actual pid_output = pid(pid_input) # notify({ # 'altitude': altitude, # 'target': target, # 'actual': actual, # 'input': pid_input, # 'output': pid_output, # 'pos': pos(), # 'target_pos', target_pos, # }) notify( f'altitude:{altitude:.2f}, target:{target:.2f}, actual:{actual:.2f}, input:{pid_input:.2f}, output:{pid_output:.2f}, pos: {pos()}, target: {target_pos()}' ) control.throttle = base + pid_output if self.surface_altitude() < 25: ap.target_direction = pos() else: d = surface_velocity() ap.target_direction = d wait() control.throttle = 0 ap.disengage() notify('done')
def execute(self): vessel = self.vessel control = vessel.control orbit = vessel.orbit body = vessel.orbit.body rf = body.orbital_reference_frame flight = vessel.flight(rf) ksc = self.conn.space_center inclination_limit = 0.25 * math.pi # 45 degrees if abs(orbit.inclination) > inclination_limit: raise Exception('Inclination is too large') # TODO check eccentricity direction = flight.prograde direction = direction / norm(direction) angle_to_body_prograde = arccos(direction[1]) # prograde = (0,1,0) if flight.radial[1] > 0: angle_to_body_prograde = 2 * math.pi - angle_to_body_prograde #https://en.wikipedia.org/wiki/Hyperbolic_trajectory v_inf = body.orbit.speed v_inf_sq = v_inf * v_inf mu = body.gravitational_parameter r = orbit.semi_major_axis ecc = 1.0 + r * v_inf_sq / mu # departure angle relative to direction of periapsis theta = arccos(-1.0 / ecc) true_anomaly = orbit.true_anomaly true_anomaly += angle_to_body_prograde # traveling prograde true_anomaly += 0.5 * math.pi # position prograde relative to body true_anomaly += math.pi - theta true_anomaly = clamp_radians(true_anomaly) if orbit.true_anomaly < 0: true_anomaly -= 2 * math.pi ut = orbit.ut_at_true_anomaly(true_anomaly) v0 = math.sqrt(2.0 * mu / r + v_inf_sq) delta_v = v0 - orbit.orbital_speed_at(ut) node = control.add_node(ut, prograde=delta_v) next_body = body.orbit.body # all bodies in stock game with moons also have an atmosphere closest_approach = next_body.equatorial_radius + 0.7 * next_body.atmosphere_depth # TODO refine maneuver time by accounting for time to SOI change? notify('raising periapsis') while node.orbit.next_orbit.periapsis < closest_approach: node.prograde -= 1 notify('refining maneuver time') prev_periapsis = node.orbit.next_orbit.periapsis * 2 while prev_periapsis > node.orbit.next_orbit.periapsis: prev_periapsis = node.orbit.next_orbit.periapsis node.ut -= 1 notify('refining periapsis') while node.orbit.next_orbit.periapsis < closest_approach: node.prograde -= 1 while node.orbit.next_orbit.periapsis > closest_approach: node.prograde += 0.1 self.execute_next_node() ksc.warp_to(ksc.ut + vessel.orbit.time_to_soi_change + 1)
def process_tv(path, interactive, show, force_overwrite, language, choose_image, max_results, dvd_ordering): successful = [] # chop off trailing backslash if found if path[-1:] == '/': path = path[0:-1] series_image = path + '/00aa-series-cover.metathumb' if not language: language = 'en' if 'debug' in show: notify('processing', path) if not os.path.isdir(path): notify('warning', '\'' + path + '\' is not a directory') return dirname = os.path.basename(path) basename = dirname if os.path.isdir(path): # assume the directory name is a tv show name and create a # LocalSeries object using it try: series = LocalSeries(basename, language, interactive, max_results) except common.NoSeriesException as e: if 'error' in show or 'all' in show: print e return except common.ZeroMatchlist as e: if 'error' in show or 'all' in show: print e return if 'debug' in show: notify(dirname, 'matches ' + series.series_data.name) try: if os.path.isfile(series_image) and (not force_overwrite): if 'exists' in show or 'all' in show: notify(dirname, 'series poster already exists') else: series.save_poster(series_image, choose_image) except IOError as e: print >> sys.stderr, e # process each video in the directory for f in os.listdir(path): if not re.search('(\.avi|\.vob|\.iso|\.wmv|\.mkv|\.m4v|' '\.mov|\.dat|\.tp|\.ts|\.m2t|\.m2ts|' '\.flv|.mp4)$', f): continue # make a LocalEpisode object using the video's information try: episode = LocalEpisode(f, series.series_data, dvd_ordering) except common.NoEpisodeException as e: if 'error' in show or 'all' in show: print e continue # check to see if a poster and metadata file already exist if (os.path.isfile(path + '/' + episode.basename + '.metathumb') and os.path.isfile(path + '/' + episode.basename + '.xml') and (not force_overwrite)): if 'exists' in show or 'all' in show: notify(episode.basename, 'screenshot and metadata already exist') continue if 'ok' in show or 'all' in show: if not episode.episode_data: raise common.NoEpisodeException(episode.basename) notify(episode.basename, 'matches ' + episode.episode_data.name) # these are separate try blocks because if one fails # the other should still be completed try: episode.save_poster(path + '/' + episode.basename + '.metathumb') except IOError as e: print >> sys.stderr, e try: episode.save_metadata(path + '/' + episode.basename + '.xml', dvd_ordering) successful.append(path + '/' + episode.basename + episode.ext) except IOError as e: print >> sys.stderr, e return successful