| Class | Hobix::Weblog |
| In: |
lib/hobix/base.rb
lib/hobix/weblog.rb |
| Parent: | Object |
The Weblog class is the core of Hobix scripting. Although often you use it’s storage accessor to get to entries, the Weblog class itself contains weblog configuration information and methods for managing the weblog.
The following accessors are available for retrieving configuration data, all of which is stored in hobix.yaml.
| title: | The title of the weblog. |
| link: | The absolute url to the weblog. (When accessed through the class — weblog.link — this is returned as a URI.) |
| authors: | A hash, in which keys are author’s abbreviated names, paired with hashes of `name’, `url’ and `email’ information. |
| contributors: | Same structure as the authors hash. For storing information on third-party contributors. |
| tagline: | The short catchphrase associated with the weblog. |
| copyright: | Brief copyright information. |
| period: | How often is the weblog updated? Frequency in seconds. |
| path: | Complete system path to the directory containing hobix.yaml. |
| sections: | Specially tagged directories which act as independent subsites or hidden categories. |
| requires: | A list of required libraries, paired with possible configuration data for a library. |
| entry_path: | Path to entry storage. |
| skel_path: | Path to template’s directory. |
| output_path: | Path to output directory. |
| lib_path: | Path to extension library directory. |
| git: | If true, regenerations will commit to git and push the site to the blahg remote. |
One of the primary uses of the Weblog class is to coordinate regenerations of the site. More about regeneration can be found in the documentation for the regenerate method.
The Weblog class also contains handlers for template prefixes. (Templates are usually contained in `skel’).
Each `prefix’ has its accompanying skel_prefix method. So, for `index’ templates (such as index.html.erb), the skel_index method is executed and passed a block which is supplied a hash by the skel method.
Usually this hash only needs to contain :page and :entries (or :entry) items. Any other items will simply be added to the vars hash.
To give you a general idea, skel_index looks something like this:
def skel_index( path_storage, section_path ) index_entries = path_storage.lastn( @lastn ) page = Page.new( 'index', section_path ) page.prev = index_entries.last.created.strftime( "%Y/%m/index" ) page.timestamp = index_entries.first.created page.updated = path_storage.last_updated( index_entries ) yield :page => page, :entries => index_entries end
The page object is instantiated, describing where output will go. The entries list, describing which entries qualify for this prefix, is queried from storage. We then yield back to the regeneration system with our hash.
Creating your own template prefixes is simply a matter of adding a new skel method for that prefix to the Weblog class.
Since configuration is stored in YAML, you can generate the hobix.yaml configuration file by simply running to_yaml on a weblog.
require 'hobix/weblog' weblog = Hobix::Weblog.load( '/my/blahhg/hobix.yaml' ) puts weblog.to_yaml #=> --- # prints YAML configuration
On Hobix.com, only news entries are shown on the front page. The site also has `about’ and `learn’ entry paths for storing the faqs and tutorials. Although I didn’t want to display the complete text of these items, I did want a sidebar to contain links to them.
So I added a `sidebar’ prefix, which loads from these entry paths. I have a sidebar.html.erb, which is included using Apache SSIs. The advantage to this approach is that when an update occurs in either of these paths, the sidebar will be updated in the next regeneration. Rather than having to regenerate every page in the site to see the change reflected.
I added a `lib/hobix.com.rb’ to the site’s `lib’ directory. And in hobix.yaml, I included a line requiring this file. The file simply contains the new skel method.
module Hobix class Weblog def skel_sidebar( path_storage, section_path ) ## Load `about' and `learn' entries abouts = path_storage.find( :all => true, :inpath => 'about' ).reverse learns = path_storage.find( :all => true, :inpath => 'learn' ).reverse ## Create page data page = Page.new( 'sidebar', section_path ) page.updated = path_storage.last_updated( abouts + learns ) yield :page => page, :about_entries => abouts, :learn_entries => learns end end end
There is a lot going on here. I’ll try to explain the most vital parts and leave the rest up to you.
First, storage queries don’t return full Entry objects. You can read more about this in the +Hobix::BaseStorage+ class docs. The storage query returns Arrays which contain each entry’s id (a String) and the entry’s modification time (a Time object).
See, the regeneration system will do the business of loading the full entries. The skel method’s job is just to report which entries qualify for a template. The regeneration system will only load those entries if an update is needed.
We create a Page object, which dictates that the output will be saved to /sidebar.ext. A modification time is discovered by passing a combined list to +Hobix::BaseStorage#last_updated+. The updated property is being set to the latest timestamp among the about and learn entries.
PLEASE NOTE: The updated property is very important. The regeneration system will use this timestamp to determine what pages need updating. See +Hobix::Weblog#regenerate+ for more.
We then yield to the regeneration system. Note that any hash key which ends with `entries’ will have its contents loaded as full Entry objects, should the prefix qualify for regeneration.
The page_storage variable passed into the method is a trimmed copy of the +Weblog#storage+ variable.
So, if you have a template skel/index.html.quick, then this template will be passed a path_storage variable which encompasses all entries. However, for template skel/friends/eric/index.html.quick will be given a path_storage which includes only entries in the `friends/eric’ path.
The simple rule is: if you want to have access to load from the entire weblog storage, use storage. If you want your template to honor its path, use path_storage. Both are +Hobix::BaseStorage+ objects and respond to the same methods.
| hobix_yaml | [R] | |
| path | [RW] |
# File lib/hobix/base.rb, line 295 295: def self.add_entry_class( c ) 296: @@entry_classes << c 297: end
# File lib/hobix/weblog.rb, line 851 851: def authorize( user, pass ) 852: require 'digest/sha1' 853: authors[user]['password'] == Digest::SHA1.new( pass ) 854: end
Used by regenerate to construct the vars hash by calling the appropriate skel method for each page.
# File lib/hobix/weblog.rb, line 430 430: def build_pages( page_name ) 431: vars = {} 432: paths = page_name.split( '/' ) 433: loop do 434: try_page = paths.join( '_' ).gsub('-','_') 435: if respond_to? "skel_#{ try_page }" 436: section_path = File.dirname( page_name ) 437: path_storage = storage.path_storage( section_path ) 438: method( "skel_#{ try_page }" ).call( path_storage, section_path ) do |vars| 439: vars[:weblog] = self 440: raise TypeError, "No `page' variable returned from skel_#{ try_page }." unless vars[:page] 441: yield vars 442: end 443: return 444: end 445: break unless paths.slice!( -2 ) ## go up a directory 446: end 447: vars[:weblog] = self 448: vars[:page] = Page.new( page_name ) 449: vars[:page].timestamp = Time.now 450: yield vars 451: end
# File lib/hobix/weblog.rb, line 364 364: def central_ext; @central_ext =~ /^\w*$/ ? @central_ext.untaint : default_central_ext; end
# File lib/hobix/weblog.rb, line 363 363: def central_prefix; @central_prefix =~ /^[\w\.]+$/ ? @central_prefix.untaint : default_central_prefix; end
Method to commit to the local git repo and push pure happiness to the remote server named blahg (which should be of webserving character and a pleasant demeanor).
# File lib/hobix/weblog.rb, line 659 659: def commit_to_git 660: puts `git add .` 661: puts `git commit -a -m "New poshts for the syhtt"` 662: puts `git push blahg master` 663: end
# File lib/hobix/weblog.rb, line 365 365: def entry_class( tag = nil ) 366: tag = @entry_class =~ /^[\w:]+$/ ? @entry_class.untaint : default_entry_class unless tag 367: 368: found_class = nil 369: if @@entry_classes 370: found_class = @@entry_classes.find do |c| 371: tag == c.name.split( '::' ).last.downcase 372: end 373: end 374: 375: begin 376: found_class || Hobix.const_find( tag ) 377: rescue NameError => e 378: raise NameError, "No such entry class #{ tag }" 379: end 380: end
# File lib/hobix/weblog.rb, line 359 359: def entry_path; File.expand_path( @entry_path || default_entry_path, @path ).untaint; end
Translate paths relative to the weblahhg’s URL. This is especially important if a weblog isn’t at the root directory for a domain.
# File lib/hobix/weblog.rb, line 404 404: def expand_path( path ) 405: File.expand_path( path.gsub( /^\/+/, '' ), self.link.path.gsub( /\/*$/, '/' ) ).gsub( /^C:/, '') 406: end
# File lib/hobix/weblog.rb, line 487 487: def facet_for( app ) 488: facets.each { |p| return if p.get app } 489: Hobix::BaseFacet.not_found app 490: end
Returns an Array of all facet plugins in use. (There can be many.)
# File lib/hobix/weblog.rb, line 483 483: def facets 484: @plugins.find_all { |p| p.is_a? BaseFacet } 485: end
# File lib/hobix/weblog.rb, line 381 381: def index_class( tag = nil ) 382: tag = @index_class =~ /^[\w:]+$/ ? @index_class.untaint : default_index_class unless tag 383: begin 384: Hobix.const_find( tag ) 385: rescue NameError => e 386: raise NameError, "No such index class #{ tag }" 387: end 388: end
# File lib/hobix/weblog.rb, line 830 830: def join_path( prefix, suffix ) 831: case prefix 832: when '', '.' 833: suffix 834: else 835: "#{ prefix }/#{ suffix }" 836: end 837: end
# File lib/hobix/weblog.rb, line 362 362: def lib_path; File.expand_path( @lib_path || default_lib_path, @path ).untaint; end
# File lib/hobix/weblog.rb, line 390 390: def link 391: URI::parse( @link.gsub( /\/$/, '' ) ).extend Hobix::UriStr 392: end
# File lib/hobix/weblog.rb, line 394 394: def linklist 395: if @linklist.class == ::Array 396: YAML::transfer( 'hobix.com,2004/linklist', {'links' => @linklist} ) 397: else 398: @linklist 399: end 400: end
Loads an entry from storage, first validating that the author is listed in the weblog config.
# File lib/hobix/weblog.rb, line 843 843: def load_and_validate_entry( entry_id ) 844: entry = storage.load_entry( entry_id ) 845: unless authors.has_key?( entry.author ) 846: raise AuthorNotFound, "Invalid author '#{ entry.author }' found in entry #{ entry_id }" 847: end 848: entry 849: end
For convenience, storage queries can be made through the Weblog class. Queries will return the full Entry data, though, so it’s best to use this only when you’re scripting and need data quick.
# File lib/hobix/weblog.rb, line 859 859: def method_missing( methId, *args ) 860: if storage.respond_to? methId 861: storage.method( methId ).call( *args ).collect do |e| 862: load_and_validate_entry( e.id ) 863: end 864: end 865: end
Built from the map of output destinations described by output_map, this map pairs entry IDs against their canonical destinations. The @central_prefix and @central_ext variables determine what output is canonical.
# File lib/hobix/weblog.rb, line 550 550: def output_entry_map 551: output_map 552: @output_entry_map 553: end
Reads skel_path for templates and builds a hash of all the various output files which will be generated. This method will cache the output_map once. Subsequent calls to output_map will quickly return the cached hash. To reset the cache, use reset_output_map.
# File lib/hobix/weblog.rb, line 499 499: def output_map 500: @output_map ||= nil 501: return @output_map if @output_map 502: path_watch = {} 503: @output_entry_map = {} 504: Find::find( skel_path ) do |path| 505: path.untaint 506: if File.basename(path)[0] == ?. 507: Find.prune 508: elsif not FileTest.directory? path 509: tpl_path = path.gsub( /^#{ Regexp::quote( skel_path ) }\/?/, '' ) 510: output = outputs.detect { |p| if tpl_path =~ /\.#{ p.extension }$/; tpl_path = $`; end } 511: if output 512: ## Figure out template extension and output filename 513: page_name, tpl_ext = tpl_path.dup, '' 514: while page_name =~ /\.\w+$/; page_name = $`; tpl_ext = $& + tpl_ext; end 515: next if tpl_ext.empty? 516: ## Build the output pages 517: build_pages( page_name ) do |vars| 518: ## Extension and Path 519: vars[:page].add_ext( tpl_ext ) 520: vars[:template] = path 521: vars[:output] = output 522: eid = ( vars[:entry] && vars[:entry].id ) || page_name 523: if not @output_entry_map[ eid ] 524: @output_entry_map[ eid ] = vars 525: elsif tpl_ext.split( '.' )[1] == central_ext 526: @output_entry_map[ eid ] = vars 527: end 528: 529: ## If output by a deeper page, skip 530: pub_name, = path_watch[vars[:page].link] 531: next if pub_name and !( vars[:page].link.index( page_name ) == 0 and 532: page_name.length > pub_name.length ) 533: 534: path_watch[vars[:page].link] = [page_name, vars] 535: end 536: end 537: end 538: end 539: @output_map = {} 540: path_watch.each_value do |page_name, vars| 541: @output_map[page_name] ||= [] 542: @output_map[page_name] << vars 543: end 544: @output_map 545: end
# File lib/hobix/weblog.rb, line 361 361: def output_path; File.expand_path( @output_path || default_output_path, @path ).untaint; end
Returns an Array of all output plugins in use. (There can be many.)
# File lib/hobix/weblog.rb, line 471 471: def outputs 472: @plugins.find_all { |p| p.is_a? BaseOutput } 473: end
Prints publication information the screen. Override this if you want to suppress output or change the display.
# File lib/hobix/weblog.rb, line 869 869: def p_publish( obj ) 870: puts "## Page: #{ obj.link }, updated #{ obj.updated }" 871: end
Returns an Array of all publisher plugins in use. (There can be many.)
# File lib/hobix/weblog.rb, line 477 477: def publishers 478: @plugins.find_all { |p| p.is_a? BasePublish } 479: end
Regenerates the weblog, processing templates in skel_path with the data found in entry_path, storing output in output_path.
The how parameter dictates how this is done, Currently, if how is nil the weblog is completely regen’d. If it is :update, the weblog is only upgen’d.
It’s very important to know how updates work, especially if you are writing custom skel methods or devious new kinds of templates. When performing an update, this method will skip pages if the following conditions are met:
To ensure that your custom methods and templates are qualifying to be skipped on an upgen, be sure to set the updated timestamp of the Page object to the latest date of the content’s modification.
# File lib/hobix/weblog.rb, line 583 583: def regenerate( how = nil ) 584: retouch nil, how 585: end
Clears the hash used to cache the results of output_map.
# File lib/hobix/weblog.rb, line 493 493: def reset_output_map; @output_map = nil; end
# File lib/hobix/weblog.rb, line 586 586: def retouch( only_path = nil, how = nil ) 587: published = {} 588: published_types = [] 589: output_map.each do |page_name, outputs| 590: puts "[Building #{ page_name } pages]" 591: outputs.each do |vars| 592: full_out_path = File.join( output_path, vars[:page].link.split( '/' ) ) 593: ## If retouching, skip pages outside of path 594: next if only_path and vars[:page].link.index( "/" + only_path ) != 0 595: 596: ## If updating, skip any that are unchanged 597: next if how == :update and 598: File.exists?( full_out_path ) and 599: File.mtime( vars[:template] ) < File.mtime( full_out_path ) and 600: ( vars[:page].updated.nil? or 601: vars[:page].updated < File.mtime( full_out_path ) ) 602: 603: p_publish vars[:page] 604: vars.keys.each do |var_name| 605: case var_name.to_s 606: when /entry$/ 607: unless vars[:no_load] 608: vars[var_name] = load_and_validate_entry( vars[var_name].id ) 609: end 610: when /entries$/ 611: unless vars[:no_load] 612: vars[var_name].collect! do |e| 613: load_and_validate_entry( e.id ) 614: end 615: end 616: vars[var_name].extend Hobix::EntryEnum 617: end 618: end 619: 620: ## Publish the page 621: vars = vars.dup 622: output = vars.delete( :output ) 623: template = vars.delete( :template ) 624: txt = output.load( template, vars ) 625: ## A plugin perhaps needs to change the output page name 626: full_out_path = File.join( output_path, vars[:page].link.split( '/' ) ) 627: saved_umask = File.umask( 0002 ) rescue nil 628: begin 629: File.makedirs( File.dirname( full_out_path ) ) 630: File.open( full_out_path, 'w' ) do |f| 631: f << txt 632: end 633: ensure 634: File.umask( saved_umask ) rescue nil 635: end 636: published[vars[:page].link] = vars[:page] 637: published_types << page_name 638: end 639: end 640: published_types.uniq! 641: publishers.each do |p| 642: if p.respond_to? :watch 643: if p.watch & published_types != [] 644: p.publish( published ) 645: end 646: else 647: p.publish( published ) 648: end 649: end 650: 651: commit_to_git if @git 652: 653: reset_output_map 654: end
Save the weblog configuration to its hobix.yaml (or optionally provide a path where you would like to save.)
# File lib/hobix/weblog.rb, line 418 418: def save( file = @hobix_yaml ) 419: unless file 420: raise ArgumentError, "Missing argument: path to save configuration (0 of 1)" 421: end 422: File::open( file, 'w' ) do |f| 423: YAML::dump( self, f ) 424: end 425: self 426: end
Receive a Hash pairing all section ids with the options for that section.
# File lib/hobix/weblog.rb, line 784 784: def sections( opts = nil ) 785: sections = Marshal::load( Marshal::dump( @sections ) ) 786: observes = !sections.values.detect { |s| s['observe'] } 787: storage.sections.each do |s| 788: sections[s] ||= {} 789: sections[s]['observe'] ||= sections[s].has_key?( 'ignore' ) ? !sections[s]['ignore'] : observes 790: sections[s]['ignore'] ||= !sections[s]['observe'] 791: end 792: sections 793: end
Returns an Array of entry paths ignored by general querying. Storage plugins must withhold these entries from queries, unless the :all => true setting is passed to the query.
# File lib/hobix/weblog.rb, line 809 809: def sections_ignored 810: sections.collect do |k, v| 811: k if v['ignore'] 812: end.compact 813: end
Returns a hash of special sorting cases. Key is the entry path, value is the sorting method. Storage plugins must honor these default sorts.
# File lib/hobix/weblog.rb, line 798 798: def sections_sorts 799: @sections.inject( {} ) do |sorts, set| 800: k, v = set 801: sorts[k] = v['sort_by'] if v['sort_by'] 802: sorts 803: end 804: end
Handler for templates with `daily’ prefix. These templates will receive a list of entries for each day that has at least one entry created in its time period. This handler requests daily pages to be output as `/%Y/%m/%d.ext’.
# File lib/hobix/weblog.rb, line 681 681: def skel_daily( path_storage, section_path ) 682: entry_range = path_storage.find 683: first_time, last_time = entry_range.last.created, entry_range.first.created 684: start = Time.mktime( first_time.year, first_time.month, first_time.day, 0, 0, 0 ) + 1 685: stop = Time.mktime( last_time.year, last_time.month, last_time.day, 23, 59, 59 ) 686: days = [] 687: one_day = 24 * 60 * 60 688: until start > stop 689: day_entries = path_storage.within( start, start + one_day - 1 ) 690: days << [day_entries.last.created, day_entries] unless day_entries.empty? 691: start += one_day 692: end 693: days.extend Hobix::Enumerable 694: days.each_with_neighbors do |prev, curr, nextd| 695: page = Page.new( curr[0].strftime( "%Y/%m/%d" ), section_path ) 696: page.prev = prev[0].strftime( "%Y/%m/%d" ) if prev 697: page.next = nextd[0].strftime( "%Y/%m/%d" ) if nextd 698: page.timestamp = curr[0] 699: page.updated = path_storage.last_updated( curr[1] ) 700: yield :page => page, :entries => curr[1] 701: end 702: end
Handler for templates with `entry’ prefix. These templates will receive one entry for each entry in the weblog. The handler requests entry pages to be output as `/shortName.ext’.
# File lib/hobix/weblog.rb, line 747 747: def skel_entry( path_storage, section_path ) 748: all_entries = [path_storage.find] 749: all_entries += sections_ignored.collect { |ign| path_storage.find( :all => true, :inpath => ign ) } 750: all_entries.each do |entry_set| 751: entry_set.extend Hobix::Enumerable 752: entry_set.each_with_neighbors do |nexte, entry, prev| 753: page = Page.new( entry.id ) 754: page.prev = prev.id if prev 755: page.next = nexte.id if nexte 756: page.timestamp = entry.created 757: page.updated = path_storage.updated( entry.id ) 758: yield :page => page, :entry => entry 759: end 760: end 761: end
Handler for templates with `index’ prefix. These templates will receive entries loaded by +Hobix::BaseStorage#lastn+. Only one index page is requested by this handler.
# File lib/hobix/weblog.rb, line 668 668: def skel_index( path_storage, section_path ) 669: index_entries = path_storage.lastn( @lastn ) 670: page = Page.new( 'index', section_path ) 671: page.prev = index_entries.last.created.strftime( "%Y/%m/index" ) 672: page.timestamp = index_entries.first.created 673: page.updated = path_storage.last_updated( index_entries ) 674: yield :page => page, :entries => index_entries 675: end
Handler for templates with `monthly’ prefix. These templates will receive a list of entries for each month that has at least one entry created in its time period. This handler requests monthly pages to be output as `/%Y/%m/index.ext’.
# File lib/hobix/weblog.rb, line 708 708: def skel_monthly( path_storage, section_path ) 709: months = path_storage.get_months( path_storage.find ) 710: months.extend Hobix::Enumerable 711: months.each_with_neighbors do |prev, curr, nextm| 712: entries = path_storage.within( curr[0], curr[1] ) 713: page = Page.new( curr[0].strftime( "%Y/%m/index" ), section_path ) 714: page.prev = prev[0].strftime( "%Y/%m/index" ) if prev 715: page.next = nextm[0].strftime( "%Y/%m/index" ) if nextm 716: page.timestamp = curr[1] 717: page.updated = path_storage.last_updated( entries ) 718: yield :page => page, :entries => entries 719: end 720: end
# File lib/hobix/weblog.rb, line 360 360: def skel_path; File.expand_path( @skel_path || default_skel_path, @path ).untaint; end
Handler for templates with `section’ prefix. These templates will receive all entries below a given directory. The handler requests will be output as `/section/index.ext’.
# File lib/hobix/weblog.rb, line 766 766: def skel_section( path_storage, section_path ) 767: section_map = {} 768: path_storage.all.each do |entry| 769: dirs = entry.id.split( '/' ) 770: while ( dirs.pop; dirs.first ) 771: section = dirs.join( '/' ) 772: section_map[ section ] ||= [] 773: section_map[ section ] << entry 774: end 775: end 776: section_map.each do |section, entries| 777: page = Page.new( "/#{ section }/index" ) 778: page.updated = path_storage.last_updated( entries ) 779: yield :page => page, :entries => entries 780: end 781: end
Handler for templates with `tags’ prefix. These templates will
receive a tag with all entries tagged with it. The handler requests will be
output as `/tags/
# File lib/hobix/weblog.rb, line 818 818: def skel_tags( path_storage, section_path ) 819: # Get a list of all known tags 820: tags = path_storage.find( :all => true ).map { |e| e.tags }.flatten.uniq 821: 822: tags.each do |tag| 823: entries = path_storage.find.find_all { |e| e.tags.member? tag } 824: page = Page.new( File::join( 'tags',tag,'index' ), section_path ) 825: page.updated = path_storage.last_updated( entries ) 826: yield :page => page, :entries => entries 827: end 828: end
Handler for templates with `yearly’ prefix. These templates will receive a list of entries for each month that has at least one entry created in its time period. This handler requests yearly pages to be output as `/%Y/index.ext’.
# File lib/hobix/weblog.rb, line 726 726: def skel_yearly( path_storage, section_path ) 727: entry_range = path_storage.find 728: first_time, last_time = entry_range.last.created, entry_range.first.created 729: years = (first_time.year..last_time.year).collect do |y| 730: [ Time.mktime( y, 1, 1 ), Time.mktime( y + 1, 1, 1 ) - 1 ] 731: end 732: years.extend Hobix::Enumerable 733: years.each_with_neighbors do |prev, curr, nextm| 734: entries = path_storage.within( curr[0], curr[1] ) 735: page = Page.new( curr[0].strftime( "%Y/index" ), section_path ) 736: page.prev = prev[0].strftime( "%Y/index" ) if prev 737: page.next = nextm[0].strftime( "%Y/index" ) if nextm 738: page.timestamp = curr[1] 739: page.updated = path_storage.last_updated( entries ) 740: yield :page => page, :entries => entries 741: end 742: end
After the weblog is initialize, the start method is called with the full system path to the directory containing the configuration.
This method sets up all the paths and loads the plugins.
# File lib/hobix/weblog.rb, line 323 323: def start( hobix_yaml ) 324: @hobix_yaml = hobix_yaml 325: @path = File.dirname( hobix_yaml ) 326: @sections ||= {} 327: if File.exists?( lib_path ) 328: $LOAD_PATH << lib_path 329: end 330: @plugins = [] 331: @requires.each do |req| 332: opts = nil 333: unless req.respond_to? :to_str 334: req, opts = req.to_a.first 335: end 336: plugin_conf = File.join( @path, req.gsub( /\W+/, '.' ) ) 337: if File.exists? plugin_conf 338: puts "*** Loading #{ plugin_conf }" 339: plugin_conf = YAML::load_file plugin_conf 340: if opts 341: opts.merge! plugin_conf 342: else 343: opts = plugin_conf 344: end 345: end 346: @plugins += Hobix::BasePlugin::start( req, opts, self ) 347: end 348: end
Returns the storage plugin currently in use. (There can be only one per weblog.)
# File lib/hobix/weblog.rb, line 465 465: def storage 466: @plugins.detect { |p| p.is_a? BaseStorage } 467: end


Summary
- Food loss occurs in many ways. Losses due to negligence or wastage, post harvest losses due to insects, rodents and microorganisms etc. and the possibility of invisible losses of food and nutrients due to processing or cooking.
- Food processing helps in blending food ingredients in various ways to obtain delicate flavor, texture and colour, which appeal to the senses.
- During cooking of starchy food, starch gets cooked and becomes sticky and soft. Proper cooking of starchy food facilitates fast digestibility due to easy breakdown of carbohydrates into glucose by enzyme (e.g. amylase) activity.
- During cooking of protein food, the nature of protein changes. This process is called protein denaturation. These changes may be beneficial or harmful.
- Heating should not always be viewed in a negative sense. Destruction of trypsin inhibitor, other anti-nutritional factors and detoxification (e.g. cooking manioc in open pans) due to heat are advantages. It increases palatability and digestibility too.
- Microorganism are capable of converting certain components in food into a more palatable form, enhancing flavor, improving texture and nutritive value and preserving food.
- Keep iodated salt in a covered, dark container, away from heat and direct sunlight.
- Steamed parboiled rice is more nutritious than raw rice since this process helps to preserve most water soluble vitamins. Parboiled rice has another advantage for adults and diabetic patients in particular, as it does not rapidly increase blood glucose after consumption.
- Milk is a very good source of riboflavin and therefore for preservation; milk and their products should not be exposed to direct sunlight.


Clicking on a dot in the indicator will move the wizard one step forward or backward depending on the side that was clicked.
Clicking on a dot in the indicator will move the wizard to the corresponding step.


Blabber
Blab about stuff
You and Where and Blab!
Next
Blabbing as {{my.screen_name}}
Change!
Go!
Blabbing in {{my.room_name}}
Leave!
Blab!
{{message.screen_name}}
{{message.content}}
No blabs yet!


TensorFlow.js Example - Iris Flower Classification
First, train the model. Then, use the text boxes to try any dummy data.
Train
Sepal Length:
Sepal Width:
Petal Length:
Petal Width:
Predict!
Result


Please answer each question below according to your personal experience.
*The fields in red are mandatory, please fill them.
1 - First Name:
2 - Last Name:
3 - Please indicate your Age:
4 - Please indicate your gender:
5 - Please provide your Postal Code:
6 - Do you practice sports regularly?
7 - Do you smoke?
8 - Do you drink (Alcohol)?
9 - Check below to inform your family history of diseases
10 - Check below to inform the allergies you have:
11 - Please, provide us your telephone number, so we can inform you about the final results of our survey:
12 - Please, provide us your email as well:


Unlabeled Image Pairs
For each city, we collect 1600 unlabeled image pairs which are taken at the same location but different times.
Valuable temporal information is embeded in these image pairs, which facilitates the mining of static-object priors.
For more details about the mining of static-object priors, please refer to our paper.


Api endpoints
- GET /api -- returns this home page.
- GET /api/topics -- returns all topics.
- GET /api/topics/:topic_slug/articles -- returns all articles for a specific topic.
- POST /api/topics/:topic_slug/articles -- adds a new article to a topic. Requires a JSON object containing both
'title' and 'body' keys.
- GET /api/articles -- returns all articles.
- GET /api/articles/:article_id -- returns a specific article.
- PATCH /api/articles/:article_id -- increments or decrements the vote score of an article by one. Requires a
vote query of either 'up' or 'down'.
- GET /api/articles/:article_id/comments -- returns all of the comments for a specific article.
- POST /api/articles/:article_id/comments -- adds a new article to a comment. Requires a JSON object contain 'body'
and 'created_by' keys.
- PATCH /api/comments/:comment_id -- increments or decrements the votes of a comment by one. Required a vote query
of "up" or "down".
- DELETE /api/comments/:comment_id -- deletes a specific comment.
- GET /api/users/:username -- returns the profile data for a specific user.


|
SideCar
|
An XML-RPC remote controller abstract base class. More...
#include </Users/howes/src/sidecar/Algorithms/RemoteControllerBase.h>
Public Types | |
| using | ZCPublisherRef = boost::shared_ptr< Zeroconf::Publisher > |
Public Member Functions | |
| RemoteControllerBase (const char *zerconfType) | |
| Constructor. More... | |
| ~RemoteControllerBase () | |
| Destructor. More... | |
| bool | start (const std::string &serviceName, long threadFlags=THR_NEW_LWP|THR_JOINABLE|THR_INHERIT_SCHED, long priority=ACE_DEFAULT_THREAD_PRIORITY) |
| Start the remote controller. More... | |
| bool | stop () |
| Stop the remote controller. More... | |
| int | close (u_long flags=0) override |
| Shutdown the controller if it is running. More... | |
Static Public Member Functions | |
| static Logger::Log & | Log () |
| Log device for objects of this type. More... | |
Protected Member Functions | |
| virtual void | installServices (XmlRpc::XmlRpcServer *server)=0 |
| Install the XML-RPC event handlers. More... | |
| virtual void | serviceNameChanged (const std::string &name) |
| Notification from the Zeroconf connection publisher that our name changed due to a conflict. More... | |
An XML-RPC remote controller abstract base class.
Allows an XML-RPC server to run within the ACE framework. Derived classes must define an installServices() method to install handlers for external XML-RPC requests.
Definition at line 22 of file RemoteControllerBase.h.
| RemoteControllerBase::RemoteControllerBase | ( | const char * | zerconfType | ) |
Constructor.
| zeroconfType | identifier to use to identify the service in mDNS |
Definition at line 27 of file RemoteControllerBase.cc.
| RemoteControllerBase::~RemoteControllerBase | ( | ) |
|
override |
|
protectedpure virtual |
Install the XML-RPC event handlers.
Derived classes must define.
| server | the XML-RPC server to install into |
Referenced by start().
|
static |
Log device for objects of this type.
Definition at line 21 of file RemoteControllerBase.cc.
References Logger::Log::Find().
Referenced by close(), RemoteControllerBase(), start(), stop(), and ~RemoteControllerBase().
|
inlineprotectedvirtual |
Notification from the Zeroconf connection publisher that our name changed due to a conflict.
Derived classes may override to receive this notification.
| name | the new service name |
Definition at line 84 of file RemoteControllerBase.h.
Referenced by start().
| bool RemoteControllerBase::start | ( | const std::string & | serviceName, |
| long | threadFlags = THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED , |
||
| long | priority = ACE_DEFAULT_THREAD_PRIORITY |
||
| ) |
Start the remote controller.
Creates a new XML-RPC server, registers remote methods with the server, and then creates a new Zeroconf::Publisher to announce the availability of the XML-RPC server. Spawns a new thread that gives time to the XML-RPC server. The thread runs the method svc().
| name | of the Zeroconf service to publish under \return true if successful, false otherwise |
Definition at line 56 of file RemoteControllerBase.cc.
References installServices(), Log(), LOGERROR, LOGFATAL, LOGINFO, and serviceNameChanged().
| bool RemoteControllerBase::stop | ( | ) |
Stop the remote controller.
Signals the XML-RPC processing thread to stop, then waits for the thread to exit. After the thread has terminated, the routine stops and disposes of the Zeroconf::Publisher object, and then deletes the XML-RPC server.
Definition at line 132 of file RemoteControllerBase.cc.
References Log(), LOGDEBUG, LOGERROR, and LOGINFO.
Referenced by close().


Home
Test
Test with 'foo' argument
Nested root
Nested test
Nested test with 'foo' argument
Missing route
Route handlers will present messages here


Moving Credentialing Forward
About
Staff
Board
Careers
Advisory Groups
Higher Education
Business
Certification & Licensure
Quality Assurance
Technical
Credential Registry
Registry Participants
User Applications
News, Events, & Resources
Fact Sheets
Contact
Powered by:
Competency Framework Editor
Login
© Copyright 2017 Credential Engine


public interface SoftStoppable
You may create a class that is inherited by Runnable
and SoftStoppable to create a Runnable that you
can stop using the softStop()
Method. So you do not need to hard-stop the Thread it is running in.
| Modifier and Type | Method and Description |
|---|---|
boolean |
running()
Defines, whether or not the inheriting class is Running.
|
void |
softStop()
This Method will stop the internal Mechanisms without stopping the thread it is running within.
|
void softStop()
boolean running()
softStop()
was not called yet, else falseCopyright © 2018. All rights reserved.


Tax Incentives
Federal and provincial tax incentive information.
Co-operative Education and Apprenticeship Tax Credits
Helps businesses recruit and retain workers.
2014 Budget Tax Changes
Take a look at the taxation changes that were announced in the 2014 Budget Address.
(PDF, 86 KB)
Health and Post Secondary Education Tax Levy
Taxation
Division
Check out the other taxes administered by the Taxation division of Manitoba Finance.
Canada Revenue Agency
Learn about your obligations and entitlements under federal law. This section also explains the different kinds of business structures, income tax reporting and payment, payroll deductions, electronic services, GST, and how to prepare for an audit.


Theoretical Love Song is a cycle of choral works exploring the possibilities of experience in novel social situations, by nature instantiated with eye contact and vocalization. The individual, the group, the time, and the setting are combined in a metaphysical reaction which can result in love, hate, or anything in between. Let’s see what this sounds like.


Prada Launches Outdoor-Inspired "Escape" Capsule
Functional pieces with an elevated sensibility.
by Nia GroceThe great outdoors is calling and Prada is the latest brand to answer by interpreting the rugged aesthetic in its own way, presenting a new travel-inspired “Escape” capsule. Encompassing men’s and women’s apparel and accessories, the lifestyle collection embodies practical elements that keep the adventurous type in mind, while the Italian label’s luxe sensibility is threaded throughout with elevated fabrics and embellishments.
The color palette spans earthy shades like khaki green, orange and tan, while camouflage and florals provide vibrant prints. Standout pieces like the gabardine nylon-coated outerwear and pants offer a protective head-to-toe look, while delicate knits and updated interpretations of the double match shirt bring in a more stylish aspect. Details like cargo pockets and zippered compartments bolster the utilitarian aesthetic throughout, while belt bags, backpacks and reusable water bottles bring in functional accessories. Thick-soled boots and chunky sneakers finish off the fits with sturdy footwear.
Prada’s Escape collection is out now at Prada Broadway Epicenter and will roll out to the Prada Design District location starting on November 27. It will be available until December 15.
For more fashion from the brand, check out the recent release of its Block Low sneaker.


Please select a burger:
This is where you provide neccessary information
E-mail
Payment Methods Visa MasterCard Cash Krita
Gender


UNIQLO's Latest Artist Series Taps Into the 40-Year History of Star Wars
Deepen your connection to the Force.
by Jamier Boatman-HarrellAs tears may shed with the impending end of what fans know as Skywalker the Saga, UNIQLO‘s latest collaborative capsule extends the magic of the Star Wars franchise. The commemorative drop positions the series’ 40-year legacy into an offering that will pique nostalgia for longtime and new fans alike through the artistic vantage of three creatives: James Jarvis, Stash and Masumi Ishikawa.
Imbuing their individualistic prowess onto a variety of garments, the collection features aesthetic references emblazoned on hoodies and T-shirts. Iconography from the film — ranging from signature logos to infamous and beloved characters — appear throughout and are recast through the perspective of each artist. Every piece establishes a unique way for enthusiasts to experience and share their admiration for Star Wars.
Check out the collection in the images above and head to UNIQLO’s website to shop and view the full collection.


Oops! Server internal error
We are sorry, but the page you are looking for does not exist.
The reason is:
URL has error
Please check if the address is complete or there are extra characters; the URL is invalid
Maybe the page has been deleted, the event has been offline, etc.


MICHAEL A film review by James Berardinelli Copyright 1996 James Berardinelli
RATING (0 TO 10): 6.0 Alternative Scale: **1/2 out of ****
United States, 1996 U.S. Release Date: 12/25/96 (wide) Running Length: 1:46 MPAA Classification: PG (Mature themes, profanity) Theatrical Aspect Ratio: 1.85:1
Cast: John Travolta, William Hurt, Andie MacDowell, Robert Pastorelli, Bob Hoskins, Jean Stapleton Director: Nora Ephron Producers: Nora Ephron, Sean Daniel, and James Jacks Screenplay: Nora Ephron & Delia Ephron and Peter Dexter & Jim Quinlan Cinematography: John Lindley Music: Randy Newman U.S. Distributor: New Line Cinema
Undeterred by the universally hostile reaction to her previous holiday picture, MIXED NUTS, director Nora Ephron (SLEEPLESS IN SEATTLE) is back at it again this year with MICHAEL, the second angel-comes-to- Earth feature of the month. While this may not be quite as sweet as THE PREACHER'S WIFE, the central theme of redemption is essentially the same. And, even though the script for MICHAEL moderates its sugary flavor with a dash of cynicism, it's no stretch to guess that the film is going for the same audience that's enchanted by such life-affirming classics as A CHRISTMAS CAROL and IT'S A WONDERFUL LIFE.
John Travolta, fresh from PHENOMENON and seemingly twenty pounds heavier, plays a grungy, chain-smoking, womanizing archangel named Michael. His purpose on Earth, in this, his final mission to the planet, is "to restore a man's heart" by imitating Cupid. That man is Frank Quinlan (William Hurt), a former reporter for the CHICAGO TRIBUNE who has been reduced to writing stories for the tabloid NATIONAL MIRROR. Along with his best friend, Huey Driscoll (Robert Pastorelli), and Huey's dog, Sparky, they scour the country, looking for the unusual and the unbelievable. When they receive a letter from an elderly woman (Jean Stapleton) in Iowa claiming that she's living with an angel, the lure is too strong. The MIRROR's editor, Vartan Malt (Bob Hoskins), sends Frank, Huey, and Sparky on assignment, along with newcomer Dorothy Winters (Andie MacDowell), an "angel expert."
William Hurt, who never emotes much in any role, is essentially reprising his emotional transformation from THE DOCTOR. He starts out as a cold, remote, cynical man, but, through Michael's manipulations, he comes to realize that he still has feelings and can love someone. Hurt is excellent playing Frank before the thaw; his effectiveness diminishes greatly thereafter. Andie MacDowell is dreadfully miscast as Dorothy. She's supposed to be uncertain and vulnerable, but MacDowell never successfully conveys those characteristics, nor does she give us any particular reason to care about her character. A more interesting and energetic performance is turned in by Robert Pastorelli (ERASER), who dutifully plays the thankless role of Hurt's sidekick.
Surprisingly, Travolta, despite his top billing, stays in the background for most of the film. We don't actually see his face until twenty minutes into the running time, and, shortly thereafter, he takes a back seat (literally) to the humans. Michael's good for some one liners, but he's all charm without much personality. We like him because he's played by Travolta, not because the script gives us any real reason to. In fact, when you consider it, he's little more than a plot device.
There are times when MICHAEL seems afflicted with a split personality. There's an edginess to the script that is repeatedly blunted by the feel-good saccharine that the Ephron sisters injected into their re-writes of Pete Dexter and Jim Quinlan's original treatment. Bits of the original still come through -- Michael isn't the most sympathetic of angels, for example -- but it's in conflict with the film's prevalent tone. There's a line spoken by Michael that illustrates the Ephrons' apparent view of life: "You can never have too much sugar."
Despite scenes of Travolta dancing, MacDowell singing, and Sparky attacking Bob Hoskins, MICHAEL is a surprisingly lifeless affair. It's a little too low-key to be an effective romance and a little too soft to be anything more ambitious. Ultimately, it's neither offensive nor horrible; it's just another unspectacular, uninspired entry on Nora Ephron's erratic resume. I can't recommend MICHAEL, but it's innocuous enough to be watchable -- provided you can summon the enthusiasm to stay awake.
- James Berardinelli e-mail<EMAIL_ADDRESS>ReelViews web site: http://www.cybernex.net/~berardin
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


New Data on the Mysterious Ninth Planet X in the Solar System
The TESS space telescope, which is designed to search for exoplanets via the transit method, may have detected the mysterious Ninth Planet, also known as Planet X, in the solar system, according to scientists from the United States and Hungary.
Experts confirm that TESS can be used to trace trans-Neptunian objects, ie celestial bodies beyond the orbit of Neptune. It was clarified that there could be three celestial bodies in this case - Sedna with apparent magnitude within 20.5-20.8, a candidate for the planet dwarf 2015 BP519 with an apparent magnitude within 21.5, and object 2015 BM518 with an apparent magnitude 21.6. It turned out that the images of the three objects were blurred but recognizable.
Modeling results showed that planet X would be distinguishable as an object with an apparent magnitude between 19-24. This means that there is a hypothetical opportunity for TESS to "view" planet X.
Experts suggest that the space telescope has already observed it, but it will take a long time for the obtained data to be analyzed.


An if statement executes a segment of code only if its condition is true. A standard if statement consists of 3 segments: if, elif and else.
if condition1: # if condition1 is true, execute the code here # and ignore the rest of this if statement elif condition2: # if condition1 is false, and condition2 is true, execute the code here # and ignore the rest of this if statement else: # if none of the above conditions is True, execute the code here
An if statement doesn't necessarily has elif and else part. If it's not specified, the indented block of code will be executed when the condition is true, otherwise the whole if statement will be skipped.
i = 0 if i == 0: print 'i == 0 is True' [out]: i==0 is True
As we mentioned above, we can write some complex statements here:
p = 1 > 0 q = 2 > 3 if p and q: print 'p and q is true' elif p and not q: print 'q is false' elif q and not p: print 'p is false' else: print 'None of p and q is true' [out]: q is false


Last modified: April 14, 2014 (view archived versions)
Thanks for using our products and services (“Services”). The Services are provided by Google Inc. (“Google”), located at 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States.
By using our Services, you are agreeing to these terms. Please read them carefully.
Our Services are very diverse, so sometimes additional terms or product requirements (including age requirements) may apply. Additional terms will be available with the relevant Services, and those additional terms become part of your agreement with us if you use those Services.
You must follow any policies made available to you within the Services.
Don’t misuse our Services. For example, don’t interfere with our Services or try to access them using a method other than the interface and the instructions that we provide. You may use our Services only as permitted by law, including applicable export and re-export control laws and regulations. We may suspend or stop providing our Services to you if you do not comply with our terms or policies or if we are investigating suspected misconduct.
Using our Services does not give you ownership of any intellectual property rights in our Services or the content you access. You may not use content from our Services unless you obtain permission from its owner or are otherwise permitted by law. These terms do not grant you the right to use any branding or logos used in our Services. Don’t remove, obscure, or alter any legal notices displayed in or along with our Services.
Our Services display some content that is not Google’s. This content is the sole responsibility of the entity that makes it available. We may review content to determine whether it is illegal or violates our policies, and we may remove or refuse to display content that we reasonably believe violates our policies or the law. But that does not necessarily mean that we review content, so please don’t assume that we do.
In connection with your use of the Services, we may send you service announcements, administrative messages, and other information. You may opt out of some of those communications.
Some of our Services are available on mobile devices. Do not use such Services in a way that distracts you and prevents you from obeying traffic or safety laws.
You may need a Google Account in order to use some of our Services. You may create your own Google Account, or your Google Account may be assigned to you by an administrator, such as your employer or educational institution. If you are using a Google Account assigned to you by an administrator, different or additional terms may apply and your administrator may be able to access or disable your account.
To protect your Google Account, keep your password confidential. You are responsible for the activity that happens on or through your Google Account. Try not to reuse your Google Account password on third-party applications. If you learn of any unauthorized use of your password or Google Account, follow these instructions.
Google’s privacy policies explain how we treat your personal data and protect your privacy when you use our Services. By using our Services, you agree that Google can use such data in accordance with our privacy policies.
We respond to notices of alleged copyright infringement and terminate accounts of repeat infringers according to the process set out in the U.S. Digital Millennium Copyright Act.
We provide information to help copyright holders manage their intellectual property online. If you think somebody is violating your copyrights and want to notify us, you can find information about submitting notices and Google’s policy about responding to notices in our Help Center.
Some of our Services allow you to upload, submit, store, send or receive content. You retain ownership of any intellectual property rights that you hold in that content. In short, what belongs to you stays yours.
When you upload, submit, store, send or receive content to or through our Services, you give Google (and those we work with) a worldwide license to use, host, store, reproduce, modify, create derivative works (such as those resulting from translations, adaptations or other changes we make so that your content works better with our Services), communicate, publish, publicly perform, publicly display and distribute such content. The rights you grant in this license are for the limited purpose of operating, promoting, and improving our Services, and to develop new ones. This license continues even if you stop using our Services (for example, for a business listing you have added to Google Maps). Some Services may offer you ways to access and remove content that has been provided to that Service. Also, in some of our Services, there are terms or settings that narrow the scope of our use of the content submitted in those Services. Make sure you have the necessary rights to grant us this license for any content that you submit to our Services.
Our automated systems analyze your content (including emails) to provide you personally relevant product features, such as customized search results, tailored advertising, and spam and malware detection. This analysis occurs as the content is sent, received, and when it is stored.
If you have a Google Account, we may display your Profile name, Profile photo, and actions you take on Google or on third-party applications connected to your Google Account (such as +1’s, reviews you write and comments you post) in our Services, including displaying in ads and other commercial contexts. We will respect the choices you make to limit sharing or visibility settings in your Google Account. For example, you can choose your settings so your name and photo do not appear in an ad.
You can find more information about how Google uses and stores content in the privacy policy or additional terms for particular Services. If you submit feedback or suggestions about our Services, we may use your feedback or suggestions without obligation to you.
When a Service requires or includes downloadable software, this software may update automatically on your device once a new version or feature is available. Some Services may let you adjust your automatic update settings.
Google gives you a personal, worldwide, royalty-free, non-assignable and non-exclusive license to use the software provided to you by Google as part of the Services. This license is for the sole purpose of enabling you to use and enjoy the benefit of the Services as provided by Google, in the manner permitted by these terms. You may not copy, modify, distribute, sell, or lease any part of our Services or included software, nor may you reverse engineer or attempt to extract the source code of that software, unless laws prohibit those restrictions or you have our written permission.
Open source software is important to us. Some software used in our Services may be offered under an open source license that we will make available to you. There may be provisions in the open source license that expressly override some of these terms.
We are constantly changing and improving our Services. We may add or remove functionalities or features, and we may suspend or stop a Service altogether.
You can stop using our Services at any time, although we’ll be sorry to see you go. Google may also stop providing Services to you, or add or create new limits to our Services at any time.
We believe that you own your data and preserving your access to such data is important. If we discontinue a Service, where reasonably possible, we will give you reasonable advance notice and a chance to get information out of that Service.
We provide our Services using a commercially reasonable level of skill and care and we hope that you will enjoy using them. But there are certain things that we don’t promise about our Services.
OTHER THAN AS EXPRESSLY SET OUT IN THESE TERMS OR ADDITIONAL TERMS, NEITHER GOOGLE NOR ITS SUPPLIERS OR DISTRIBUTORS MAKE ANY SPECIFIC PROMISES ABOUT THE SERVICES. FOR EXAMPLE, WE DON’T MAKE ANY COMMITMENTS ABOUT THE CONTENT WITHIN THE SERVICES, THE SPECIFIC FUNCTIONS OF THE SERVICES, OR THEIR RELIABILITY, AVAILABILITY, OR ABILITY TO MEET YOUR NEEDS. WE PROVIDE THE SERVICES “AS IS”.
 TO THE EXTENT PERMITTED BY LAW, WE EXCLUDE ALL WARRANTIES.
WHEN PERMITTED BY LAW, GOOGLE, AND GOOGLE’S SUPPLIERS AND DISTRIBUTORS, WILL NOT BE RESPONSIBLE FOR LOST PROFITS, REVENUES, OR DATA, FINANCIAL LOSSES OR INDIRECT, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES.

If you are using our Services on behalf of a business, that business accepts these terms. It will hold harmless and indemnify Google and its affiliates, officers, agents, and employees from any claim, suit or action arising from or related to the use of the Services or violation of these terms, including any liability or expense arising from claims, losses, damages, suits, judgments, litigation costs and attorneys’ fees.
We may modify these terms or any additional terms that apply to a Service to, for example, reflect changes to the law or changes to our Services. You should look at the terms regularly. We’ll post notice of modifications to these terms on this page. We’ll post notice of modified additional terms in the applicable Service. Changes will not apply retroactively and will become effective no sooner than fourteen days after they are posted. However, changes addressing new functions for a Service or changes made for legal reasons will be effective immediately. If you do not agree to the modified terms for a Service, you should discontinue your use of that Service.
If there is a conflict between these terms and the additional terms, the additional terms will control for that conflict.
These terms control the relationship between Google and you. They do not create any third party beneficiary rights.
If you do not comply with these terms, and we don’t take action right away, this doesn’t mean that we are giving up any rights that we may have (such as taking action in the future).
If it turns out that a particular term is not enforceable, this will not affect any other terms.
The laws of California, U.S.A., excluding California’s conflict of laws rules, will apply to any disputes arising out of or relating to these terms or the Services. All claims arising out of or relating to these terms or the Services will be litigated exclusively in the federal or state courts of Santa Clara County, California, USA, and you and Google consent to personal jurisdiction in those courts.
For information about how to contact Google, please visit our contact page.


Doesn’t show supplementary text, but must show fallback text without the icon. Supplementary text is still available to screen readers.
Twitter Facebook Google Plus RSS Feed

Twitter

Doesn’t show supplementary text, must show fallback icon without the primary icon. This can be a background image or a Unicode glyph. Supplementary text is still available to screen readers.
Warning: In browsers that don’t support :before/:after (IE6-7), fallback is text.

Menu

Shows supplementary text, does not need fallback experience without the icon.
Share on Twitter (Sibling Text)

Share on Twitter (Sibling Text)


This is the pure Java implementation of the TMAP Live Access Server. There are three major components to this implementation of LAS, the Product Server, a
collection of backend services and the user interface server.
The Product Server
The LAS Product Server (LPS) is implemented as a Struts-based Web
application server (though care has been taken to keep the logic that
deals with LAS configuration files and the request and response
messages separate from the framework). The LPS typically does
work on behalf of an LAS User Interface (LUI) server, a servlet-based
Web application server responsible for presenting HTML pages to a
browser from which the user interacts with an LAS site. When the
user has completed the selections necessary to create an LAS Product,
the LUI redirects the browser to an LPS URL. The query string of
this URL contains one essential parameter (a text parameter named "xml"
which is a string representation of the UI Request XML [some outdated
documentation about these messages is available here:
http://www.ferret.noaa.gov/Ferret/LAS/Documentation/manual/reqapi.html).
The user interface model we use is for the LPS URL to be opened in a
new "output" window of the user's browser. This window
accumulates LPS URLs in its history and interacts with the LPS to give
the user feedback from long-running product requests, gives the user
the ability to cancel long-running product requests and has the
potential to make subsequent requests directly to the LPS. The
remainder of this document will deal exclusively to what happens after
the request has been received by the LPS.
The Life-cycle of a Request
The life-cycle of a LAS UI Request from its arrival at the LPS is as
follows. Using the UI Request and the LAS configuration, the LPS
(a Struts Action class called ProductServerAction) creates a
ProductRequest object. Using the newly constructed ProductRequest
object along with the LAS configuration (which has been processed when
the servlet initialized to merge the hierarchy of <property>
definitions), the LPS specific configuration (information about the
cache and the known backend services), the incoming HTTP Request
object, the Structs action mapping (this is unnecessary and will be
eliminated to separate the "Runner" thread from the Struts framework)
and a reference to the centrally maintained cache object, the LPS
constructs a ProductServerRunner object (which is a sub-class of Java
Thread). The Thread is started and the LPS joins this thread and
waits for it complete. If it completes the request or encounters
an error within the <ui_timeout> it returns the product or error
to the client. If the Thread has not finished before the
specified <ui_timeout> this Thread object is stored as an
attribute in the Struts ActionServlet context and the LPS returns a
progress page to the client (with information about how many times the
progress page has refreshed since the request started and which step in
the compound operation is currently being performed). After a 5
second delay, the browser client refreshes by sending the exact same
request to the LPS. The LPS takes the UI Request and finds the
Thread in its context that is processing this request. It joins
that Thread and again waits for the <ui_timeout> to expire or the
request to complete repeating the cycle of sending the progress page
and refreshing the browser with the same request. Eventually, the
ProductServerRunner will complete or the Backend Service will encounter
the <product_timeout> and return a timeout error.
In the event that no <ui_timeout> is set in the incoming request
(such as with a "batch" request from a command line client) the LPS
will wait forever for the ProdcutServerRunner thread to complete
without returning a progress page.
How the LPS Uses the LAS Configuration
The complexity of the operations and the mechanics of the data access
necessary to make a product are hidden from the LUI by abstractions
contained in XML configuration documents. For example, the
configuration will contain details such as the units, time, geographic
extents a particular data variable. The fact that these data
reside on a remote OPeNDAP server or in a database table is hidden from
the LUI. Likewise, the fact that creating the particular graphic
product request might require the LPS to request that information be
extracted from a database table and an intermediate netCDF file be
created and then request a plot be made from this file is also hidden
from the LUI.
Therefore, it is a large part of the job of the LPS to unwind these
hidden complexities into the specific steps needed to create the
product. It is not however, the job of the LPS to create the
intermediate and final products needed to fulfill the request.
Instead, the LPS will call upon one or more Backend Services to build
the products necessary to complete a request. We have implemented
a collection of Backend Services which we deploy in the LAS Backend
Server (LBES). The LBES is nothing more than the Apache
AxisServlet with a collection of LAS specific services deployed to the
AxisServlet via the Axis WSDL.
In order to make the translation from the abstract references to data
and operations included in the UI request to specific data access
mechanisms and backend services, the LPS translates the UI request into
an internal data structure called a ProductRequest. This
translation highlights one of the first and most important design
philosophies of the LPS architecture, the use of Plain Ordinary Java
Objects (POJOs) to hold the application specific data.
The ProductRequest POJO[2]
(a marriage between the UI Request and the LAS Configuration)
The constructor for the ProductRequest object takes as input the JDOM
Document representing the LAS Configuration information and the JDOM
Document representing UI Request XML. (Actually, all of the XML
in the LPS and LBES are internally represented by sub-classes of
LASDocument which is in turn a sub-class of JDOM Docment.) The
ProductRequest object is independent of the Web application framework
that is used to deploy the application. This means the JUnit
testing can be used to exercise all of the code that creates and
manipulates the ProductReqeust object and most importantly the
underlying Web application framework can be changed without affecting a
single line of the ProductReqeust object's code. The biggest
collection of information in the ProductRequest object is an
ArrayList<LASBackendRequest> which contains the XML documents
that will used to invoke each backend service (some preliminary
information about the LASBackendRequest XML document can be found here:
http://tmap.pmel.noaa.gov/~rhs/JPS/LBES.html). When this XML is
constructed all of the abstractions which point to data definitions in
the LAS configuration are resolved into actual data access information
either in form of file names or network resources (such as OPeNDAP
URLs). Additionally, all of the property definitions which are
contained in the LAS configuration XML are included in the XML that
defines the data access for each LAS variable include in the
request. Finally, this XML also contains concrete file names
which will be the containers for the results this operation is expected
to produce (plot images, map scale information, debug output and so
on). The construction of the ProductRequest object is also
responsible for creating the connections between compound operations
where the results from one operation are used as input into subsequent
operations.
The ProductActionRunner (the POJO that invokes the backend services)
When the ProductRequest object has been constructed, it is in turn used
to construct the ProductServerRunner, the Thread sub-class that will be
run to create the product. The ProductServerRunner Thread runs
and sequentially invokes the services necessary to create the requested
product and collates the responses.
Cache Mangement
All of the cache management occurs at the LPS before any backend
services are invoked. The first check for a cache hit is based on
the cached key generated from the UI Request. If there is a
response file in the cache that matches this key, that response file is
examined to make sure all of the individual results are still in the
cache. If so, then the LPS returns this response
immediately. If not it begins the process of invoking the
individual services needed to produce the final product. Each
individual sub-operation and its response are also cached so based on
cache keys generated from the Backend Request XML for each
sub-operation.
Individual backend service implementations are also welcome to manage a
cache independently of the LPS, but are not required to do so.
The Backend Services (and how they are
invoked and controlled)
The second important design philosophy has to do with the fact that the
actions of the Backend Services that ultimately fulfill the product
requests can be controlled by the LAS configuration. For the two
services that we have implemented so far, this behavior is achieved by
assigning a script template to each LAS operation.
For example, in the implementation of the Ferret backend service an
operation that will perform a plot in a 2D plane is defined with this
XML:
<operation name="2D Plot" ID="Plot_2D" template="output"
script="Plot_2D">
<service>ferret</service>
<args>
<!-- This can now be improved with min/max info
to be used by the UI to enforce selections. -->
<arg type="variable" index="1" />
<arg type="region" index="1" />
</args>
<response
ID="PlotResp" type="HTML" index="1">
<result type="image" ID="image1" />
<result type="image" ID="ref_map" />
<result type="map_scale" ID="map_scale" />
<result type="debug" ID="debug" />
<result type="cancel" ID="cancel" />
</response>
</operation>
The ProductServerRunner takes the ProductRequest and begins invoking
the service for each LASBackendRequest. The SOAP call to the
service is invoked and the LASBackendReqeust is passed to the backend
service as a single String argument. The "script" attribute
of this operation definition is a reference to a particular text file
in the resource path of the backend service. When the backend
service (named in the <service> element of the operation
definition) receives this request, it will process this template as
part of fulfilling the request (see below).
The Backend Services
At this point, we are ready to hop across the network to the backend
services that are needed to create the product. Each of the
backend services that we have implemented has the same basic
structure. The service is a simple class which exposes a single
method to the SOAP clients and this method accepts the
LASBackendRequest XML string as its only argument. This request
object is used to construct a Tool[1] class (which extends a generic
Tool class). The Tool class must implement a run method which
processes the request. If the Tool needs to interface with a
legacy application such as Ferret a generic Task class is available
which contains all of the infrastructure needed to run the external
Unix application (methods for constructing the Runtime class to
interface with the operating system, methods to pick up the output
streams (which is critical since process can block with buffer
overflows if this is not done correctly) and a generic methods to
search the output streams for error conditions). I have used this
Task class to run Ferret and to run Perl scripts.
When the service runs the aforementioned "script" file is what controls
the actions of the legacy application or database query. This
file is first processed as a Velocity template with the
LASBackendRequest object in its context. All of the LAS
configuration properties (that apply to this request or to the data
variables referenced by this request) and names of input and output
data files are available from the LASBackendRequest object and can
thereby be translated into Ferret symbols or placed into SQL requests
to customize the action for this particular request.
The backend service processes the request (runs the ferret or queries
the db based on the "script") and constructs and LASBackendResponse
object that will be returned to the LPS. This is a very simple
XML construct that contains the names and IDs of the output files
produced. (If the backend service is a remote service it must
return a network URL instead of a file path in the response XML).
Canceling a Request
The backend service must also be prepared to handle a request to cancel
a running request. If the LPS sends exactly the same request
again (except containing a single <cancel/> element below the
root element) the backend service should stop processing the
request. Since getting access to the thread processing the
backend request in the AxisServlet is complicated, we have implemented
this action using the file system to signal that the request has been
canceled. When the cancel request arrives the backend service
creates an empty "cancel" file (defined in the operation XML) and
immediately returns an error response indicating that the job has been
canceled (even though the thread running the backend service may or may
not have stopped processing the request at that moment).
This means that the LPS can halt the ProductServerRunner that is
processing the job and signal the user that the job has been
canceled. Meanwhile, the original thread that is processing the
job on the backend should be checking periodically (after completing
various steps along the way in the Tool and Task classes) for the
existence of the "cancel" file. If it finds the file it can stop
processing and it has no further responsibilities and does not need to
return any information to the LPS since the request that caused the
cancel file to be created has already taken care of signaling the LPS
and user that the job has been canceled.
Error Processing
If the backend service encounters an error processing the request it
constructs a special LASBackendResponse with the error information
included and the LPS will detect the error and forward to the generic
error response (shown in the diagram below).
Processing the Response
We are now ready to return to the LSP. The LASBackendResponse is
shipped back the ProductServerRunner (as a string) and the
ProductServerRunner invokes the next service in the chain or signals
the ProductServerAction that it is finished. The final task of
the ProductActionServer is to process the response it receives.
In any case, it removes the ProductActionRunner object from the Servlet
context (at that moment subsequent requests for the same product will
either get their request fulfilled from cache or will cause the product
to be regenerated). If the response contains an error the action
is forwarded to the error template which displays the error to the
user. Otherwise, if the cache is turned on the LASBackendResponse
file is added to the cache and the action is forwarded to the output
template.
This last bit of work is the final part of the design philosophy in the
new architecture. Every operation can have a template assigned to
it which tells the LPS how to display the results. The template
has access to the LASBackendResponse object and from this object it can
extract any or all of the results that are defined in the response (be
they debug text, plot output, ASCII data files and so on). It
also has access to the LASUIRequest that was used to create this
product so that it can make decisions about what to display, fill in
titles and other information based on the values of properties that are
defined for this request.
Finally, to allow the LPS to cause the browser to invoke external
applications (such as Excel with CSV files) or to allow LPS URLs to
used as the src attribute in <img> HTML tags, the LPS operations
XML allows for operations to be defined with a single streaming
result. E.g.
<result type="image" ID="plot_image" stream="true"
mime_type="image/jpg"/>
If the LPS processes a request for an operation that asks for the
output to be streamed, it sets the mime type of the response, picks up
the bytes of the output and streams them back to the client then
signals the Struts action servlet that is finished by forwarding to a
null action.
The User Interface Server
[1] The Tool class and the Task class were stolen
directly from Anagram and the implementations of Anagram used by
TMAP. These classes were designed and written by Joe Wielgosz,
Richard Rogers, Yonghua Wie.
[2] A POJO is a Plain Old Java Object as opposed to
an Enterprise JavaBean or some other elaborate and specific object type.


{% extends '../tutorials/tutbaselayout.html' %} {% load static %} {% block content %}
The following table shows all the relational operators supported by C. Assume variable A holds 10 and variable B holds 20 then −
| Operator | Description | Example |
|---|---|---|
| == | Checks if the values of two operands are equal or not. If yes, then the condition becomes true. | (A == B) is not true. |
| != | Checks if the values of two operands are equal or not. If the values are not equal, then the condition becomes true. | (A != B) is true. |
| > | Checks if the value of left operand is greater than the value of right operand. If yes, then the condition becomes true. | (A > B) is not true. |
| < | Checks if the value of left operand is less than the value of right operand. If yes, then the condition becomes true. | (A < B) is true. |
| >= | Checks if the value of left operand is greater than or equal to the value of right operand. If yes, then the condition becomes true. | (A >= B) is not true. |
| <= | Checks if the value of left operand is less than or equal to the value of right operand. If yes, then the condition becomes true. | (A <= B) is true. |
Try the following example to understand all the relational operators available in C −
#include <stdio.h>
main() {
int a = 21;
int b = 10;
int c ;
if( a == b ) {
printf("Line 1 - a is equal to b\n" );
} else {
printf("Line 1 - a is not equal to b\n" );
}
if ( a < b ) {
printf("Line 2 - a is less than b\n" );
} else {
printf("Line 2 - a is not less than b\n" );
}
if ( a > b ) {
printf("Line 3 - a is greater than b\n" );
} else {
printf("Line 3 - a is not greater than b\n" );
}
/* Lets change value of a and b */
a = 5;
b = 20;
if ( a <= b ) {
printf("Line 4 - a is either less than or equal to b\n" );
}
if ( a >= b ) {
printf("Line 5 - b is either greater than or equal to b\n" );
}
}
When you compile and execute the above program, it produces the following result −
Line 1 - a is not equal to b Line 2 - a is not less than b Line 3 - a is greater than b Line 4 - a is either less than or equal to b Line 5 - b is either greater than or equal to b


OpenFlow Information for Slice {{ slice.name }}
The following settings will apply to all OpenFlow
aggregates in the same slice automatically. There is no need to update the slice if it is started.
{% extends "base.html" %} {% load ch_extras %} {% block title %}OpenFlow Slice Information for Slice {{ slice.name }}{% endblock title %} {% block content %}


Skype: this.this
Phone: +1 567 9847
Email<EMAIL_ADDRESS>Feedback:
Skype: this.this
Phone: +1 567 9847
Email<EMAIL_ADDRESS>Feedback:
Skype: this.this
Phone: +1 567 9847
Email<EMAIL_ADDRESS>Feedback:
Skype: this.this
Phone: +1 567 9847
Email<EMAIL_ADDRESS>Feedback:
Skype: this.this
Phone: +1 567 9847
Email<EMAIL_ADDRESS>Feedback:
Skype: this.this
Phone: +1 567 9847
Email<EMAIL_ADDRESS>Feedback:
Skype: this.this
Phone: +1 567 9847
Email<EMAIL_ADDRESS>Feedback:
Skype: this.this
Phone: +1 567 9847
Email<EMAIL_ADDRESS>Feedback:


What is your name?
What is your quest?
To seek the Holy Grail.
To complete the form.
What is the airspeed velocity of an unladen swallow? (Must be greater than zero!)
What do you mean, an African or a European swallow?
Choose!
African
European
I don't know
Reveal the Truth!
Have at you and click me!


This is a span.
This is another span.
This is emphasized.
Wow, this span gets limed!!!
This is struck through.
Here is one last span.


Reconstruction: Triangulation
This post treats the reconstruction of the matching points and the results of this process.
Blog for Robotic vision
This post treats the reconstruction of the matching points and the results of this process.
This post talks about the current method used on point matching making use of OpenCV methods.
In this post is treated the first step for the reconstruction, considering different options to get a set of points to reconstruct.
In this post is explained the material and objective of the 3D reconstruction project. Given a robot with a pair of cameras and a set of figurines, the objective is getting the 3D position of some points of the real world, possibly making the robot capable of interacting with it.
This post explain the last tricks to get a fast and robust controller. To the infinity and beyond!
This post will explain some considerations to make on choosing the measured variables and some methods to achieve a better and more robust control.
This post will explain the first design of a PID controller for the line follower to make it able to do a first complete lap. PIDs are a control method based on a fast loop with feedback from some kind of sensors. In this case, the sensor is the camera and the desired control variable is the steering speed.
In this post I’ll talk about the method to process the captured images from the car so it becomes easier to extract information from them.
This is my first entry for the blog! On this blog I’ll be talking about the different purposed exercises on the JdeRobot platform. The first one is the line follower explained after this brief intro.


SCPI server application
- Enables remote control of Red Pitaya using MATLAB/Python/LabVIEW/Scilab
- Provides comlete access to Red Pitaya hardware functionalities
(GPIO, slow and fast DACs and ADCs, I2C, SPI, UART) - Supports WIFI or LAN remote interface
SCPI server is not running, press RUN button to start it
Example about how to Control your Red Pitaya using MATLAB/Python/LabVIEW/Scilab. Are available on link below


Local Weather App
Switch to
°C / Km
°F / Mi
Feels like:
Feels like:
Wind:
Wind:
Humidity:
Pressure:
Visibility:
Visibility:
UV Index:


Abandoned Mercedes-Benz SLS AMG Looks Depressing, Seized by Russian Police
by Andrei TutuSure, the wheels of this Mercedes-Benz SLS do sport the AMG logo, but there's something wrong here and it's not just the lack of tires - these aren't the original wheels, because we're looking at a vehicle that's been left at the mercy of the elements.
"How does such a Grand Tourer end up in such a situation?" one might wonder. Well, the situation of the machine surfaced via Instagram. And the pair of photos showcasing the car, which you can find at the bottom of the page, were accompanied by a brief message.
It looks like this V8 monster used to be owned by a Russian "businessman" who got in trouble, with the authorities eventually seizing the vehicle.
Sadly, it seems that the Affalterbach toy is far from being kept in proper conditions - as Google translate shows, the said post even talks about locals being able to get close to the vehicle and it's difficult to believe such an aspect could help the condition of the car. As for that popped door handle, the element has been probably left in this state so the door can be opened once the battery is out.
Of course, this reminds us of all the go-fast and luxury machines that find themselves in similar situations over in the Arab world and here's an example.
And while these images are depressing on their own, we also have to think about the cold season. After all, this SLS has to face a force that has defeated leaders such as Napoleon Bonaparte and Hitler: the Russian Winter. Oh, well, at least the Mercedes-Benz SLS AMG comes with an aluminum body.
On a happier note, here's a review to take you through the tech wonders that define the German GT, albeit with the tale covering the Mercedes-Benz SLS AMG Roadster.


Best practices
Best practices
Within an Azure AD B2C custom policy, you can integrate your own business logic to build the user experiences your require and extend functionality of the service. We have a set of best practices and recommendations to get started.
- Within the base policy, we suggest avoiding making any changes. And if required, make heavy notes. Instead, create your logic within the extension files. You can add new elements which will override the base policy by referencing the same Id. This will allow you to scale out your project while making it easier to upgrade base policy later on if Microsoft releases new starter packs.
- Configure your user journey in the extension file only.
- New elements should be added to the extension file. You can still override the technical profile configured in the base policy, in the extension file with new elements by referencing the original technical profile Id.
Customize elements defined in the base policy
- To customize any element from the base policy, you simply copy the element with its parent elements, and make the necessary changes.
- Want to add something new? That’s OK! Make sure you copy over all of those claims from the base policy.
- When overriding a Self-Asserted technical profile by adding new Output Claims, the new claim will be rendered first. To change the order, make sure you include all of the claims from the base policy and arrange the output claims in the order you require them to be rendered.
In the following example, the Facebook policy is configured in the base policy, while in the extension policy you must specify the Facebook application Id, the scopes to use and the information you want to retrieve from Facebook. The extension contains the values that are related to your environment like the scopes that are relevant to you in the interaction with Facebook.
Including technical profile
You can create a technical profile that is based on another one. Use the IncludeTechnicalProfile element to customize your technical profile.
For example AAD-UserReadUsingAlternativeSecurityId-NoError
includes AAD-UserReadUsingAlternativeSecurityId
, while configuring the RaiseErrorIfClaimsPrincipalDoesNotExist
metadata item to false
.
AAD-UserReadUsingAlternativeSecurityId
itself includes the AAD-Common
technical profile.
AAD-Common
provides the base functionality to communicate with Azure AD over the AzureActiveDirectoryProvider propriety protocol.
-
Include: When you include a technical profile, you create a new technical profile, that is based on another one. The one you create has a new name (id). You can declare a technical profile that includes any technical profile, in the same policy or in any policy that inherits from the policy where the technical profile is configured.
For example, a technical profile “A” can be included in technical profile “B1” and “B2”. B1 itself can be included in technical profile “C” and so on.
-
Overwrite. Overwrite is always done in a policy that inherits from the policy where the technical profile is declared. When you overwrite, you do not change the technical profile name. You can overwrite a technical profile that is configured in any policy which is inherited by your current working policy file.
Escape XML invalid characters
If you need to include XML invalid characters in the XML policy file, use their escaped equivalents. The following table shows the invalid XML characters and their escaped equivalents.
| Invalid XML character | Replaced with |
|---|---|
< |
< |
> |
> |
" |
" |
' |
' |
& |
& |


Earnings (Daily)
RM100.00Earnings (Monthly)
RM12315.00Earnings (Annually)
RM128093.00Earnings Overview
PM
Notification
-
Notification 1
-
Notification 2
-
Notification 3
-
Notification 4
-
Notification 5
-
Notification 6
Pending Order
-
Order 1
-
Order 2
-
Order 3
-
Order 4
-
Order 5
-
Order 6


The goal of this tool is to provide an easy way to link a specified molecule to the Tomato genome.
For any given CHEBI identifier, it will look up the Rhea database. It will search all the reactions in which this molecule is involved. Find all the protein involved in these reactions as well and retrieve the pathway of these protein as well as the gene from the Tomato genome linked to them.
Example: Search for CHEBI 17579 ie: Beta-carotene