text:
#!/usr/bin/env python

'''
MySportLife, Martin Dvorak, 2015

Licensed under the Apache License, Version 2.0 (the "License"); you may
not use this file except in compliance with the License. You may obtain
a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
'''

import yaml
'''
The beauty of Python+YAML is that YAML files are loaded
to native Python structures (lists, maps, ...). Thus YAML
drives Python trainingLog structures and code here only performs
traversal and analytics of these structures.
'''
import os
from datetime import date, datetime

'''
Design principles:
   * Self-contained Python file i.e. only single file might be distributed without
     any dependencies and use to generate MSL documentation.
   * MSL may generate defaults e.g. CSS to ~/.msl directory where it can be customed
     by users.
'''

__version__ = "0.0.1-dev"
__notes__ = "development version"
__author__ = "martin.dvorak@mindforger.com"
__license__ = "Apache License 2.0"
__url__ = "http://github.com/dvorka/my-sport-life"

l10nweekdays = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]
l10nmonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']

class MySportLife:
    '''
    Main class - loads configuration, loads all training log files, aggregates log files
    and generates HTML and/or MySportLife log with analytics.
    '''

    def __init__(self, trainingLogDirectoryPath, outputDirectoryPath):
        self.trainingLogDirectoryPath = trainingLogDirectoryPath
        self.outputDirectoryPath = outputDirectoryPath

    def generate(self):
        print 'My Sport Life:\n  {}\n    >>>\n  {}'.format(self.trainingLogDirectoryPath, self.outputDirectoryPath)
        configuration = MySportLifeConfiguration(self.trainingLogDirectoryPath+'/config.yaml')
        trainingLog = TrainingLog(configuration, self.trainingLogDirectoryPath)
        report = Report(trainingLog)
        report.calculate()
        htmlLog = HtmlLogGenerator(self.outputDirectoryPath, report)
        htmlLog.generate()

class MySportLifeException(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

class MySportLifeConfiguration:
    '''
    MySportLife configuration.
    '''

    yearFileNames = set({})

    def __init__(self, configurationFileName):
        print 'Loading configuration...'
        self.configurationFileName = configurationFileName
        stream = open(self.configurationFileName, 'r')
        self.configuration = yaml.load(stream, Loader=yaml.CLoader)

    def getConfiguration(self):
        return self.configuration

    def getYearLogFileNames(self):
        for yearFileName in self.configuration.get("inputs"):
            self.yearFileNames.add(yearFileName.get("training-log-file"))
        return self.yearFileNames

def rmDirRecursively(directoryToDelete):
    for root, dirs, files in os.walk(directoryToDelete, topdown=False):
        for name in files:
            os.remove(os.path.join(root, name))
        for name in dirs:
            os.rmdir(os.path.join(root, name))
    os.rmdir(directoryToDelete)

class TrainingLog:
    '''
    Aggregated training logs across all years.
    '''

    # all training phases (all years) ordered by time
    phases = []
    # year to list of phases ordered by time
    yearToPhases = {}

    def __init__(self, configuration, trainingLogDirectoryPath):
        print 'Loading training logs...'
        for yearFileName in configuration.getYearLogFileNames():
            yearFilePath = trainingLogDirectoryPath+"/"+yearFileName
            print '  {}'.format(yearFileName)
            yearLog = self.loadYearTrainingLogFile(yearFilePath)
            self.mergeYearTrainingLog(yearLog)

    def loadYearTrainingLogFile(self, logFileName):
        self.logFileName = logFileName
        stream = open(self.logFileName, 'r')
        return yaml.load(stream, Loader=yaml.CLoader)

    def mergeYearTrainingLog(self, yearLog):
        print "Processing {} log with {} entries...".format(yearLog["year"], len(yearLog["log"]))
        self.yearToPhases[yearLog["year"]]=yearLog["log"]
        for unit in yearLog["log"]:
            unit["year"] = yearLog.get("year")
            unit["month"] = unit.get("date").split('/')[0]
            unit["day"] = unit.get("date").split('/')[1]
            self.phases.append(unit)
        print "  {} log done".format(yearLog.get("year"))

class LifetimeActivityTotal:
    '''
    Lifetime summary for a particular sport activity - used as dictionary value.
    '''
    days = set([]);
    phases = [];
    km = 0;
    seconds = 0;

    def __init__(self):
        pass

    def add(self, phase):
        self.days.add(phase.get('date'))
        self.phases.append(phase)
        if 'distance' in phase:
            if phase['distance'].endswith('km'):
                self.km += float(phase['distance'].replace('km',''))
            else:
                raise MySportLifeException('Unknown unit used in distance {}'.format(phase['distance']))
        if 'time' in phase:
            self.seconds=MslTime(phase['time'])

class MslTime:
    '''
    Parse any of the following strings to fields:
      1h3'10.7
      1h4'
      3'10.7
      10.7
      11
      3'
      3'10
      1h3'
      1h
    '''

    hours=0
    minutes=0
    seconds=0
    tens=0

    def __init__(self, timestring):
        if 'h' in timestring:
            self.hours=int(timestring.split('h')[0])
            hourDone=timestring.split('h')[1]
            if "'" in hourDone:
                self.minutes=int(hourDone.split("'")[0])
                minutesDone=hourDone.split("'")[1]
                if '.' in minutesDone:
                    self.seconds=int(minutesDone.split(".")[0])
                    self.tens=int(minutesDone.split(".")[1])
        else:
            if "'" in timestring:
                self.minutes=int(timestring.split("'")[0])
                minutesDone=timestring.split("'")[1]
                if '.' in minutesDone:
                    self.seconds=int(minutesDone.split(".")[0])
                    self.tens=int(minutesDone.split(".")[1])
            else:
                if '.' in timestring:
                    self.seconds=int(timestring.split(".")[0])
                    self.tens=int(timestring.split(".")[1])
                else:
                    self.seconds=int(timestring)

    def getSeconds(self):
        return self.hours*60*60+self.minutes*60+self.seconds;

class Report:
    '''
    A class that performs analytics calculation on top of aggregated log.
    '''

    # set of days I was exercising
    daysWorthIt = set([])
    # set of days I was sick
    sickDays = set([])
    # set of activity types that can be found in training log
    activityTypes = set([])
    # activity type to LifetimeActivityTotal
    activities = {}

    # 2005 > Running > 27
    yearToActivityToTotalKm={}
    # 2005 > 3 > Running > 278km (ALL activity represents sum across activities; WEIGHT represents weight)
    yearToMonthToActivityToKmTimeWeight={}
    # 2005 > 22 >Running > 278km (ALL activity represents sum across activities; WEIGHT represents weight)
    yearToWeekNumberToActivityToKmTimeWeight={}

    def __init__(self, trainingLog):
        self.trainingLog = trainingLog

    def getPhasesByDistanceForActivity(self, activity):
        result = []
        self.trainingLog.phases.sort(cmp=self.comparatorPhasesByDistance, reverse=True)
        for unit in self.trainingLog.phases:
            if unit["activity"] == activity:
                result.append(unit)
        return result

    def comparatorPhasesByDistance(self, phaseA, phaseB):
        if "distance" in phaseA:
            if "distance" in phaseB:
                a=str(phaseA.get("distance"))
                b=str(phaseB.get("distance"))
                distanceA=float(a.replace("km",""))
                distanceB=float(b.replace("km",""))
                if distanceA-distanceB>0:
                    return 1
                else:
                    if distanceA==distanceB:
                        return 0
                    else:
                        return -1
            else:
                return 1
        else:
            if "distance" in phaseB:
                return -1
            else:
                return 0

    def comparatorUnitsByDate(self, unit1, unit2):
        pass
    def comparatorUnitsByDistance(self, unit1, unit2):
        pass
    def comparatorUnitsByTime(self, unit1, unit2):
        pass
    def comparatorUnitsByFeeling(self, unit1, unit2):
        pass
    def comparatorUnitsByTemperature(self, unit1, unit2):
        pass

    def distanceFieldToKm(self, s):
        return float(s.replace('km',''))
    def weightFieldToKg(self, s):
        return float(s.replace('kg',''))

    def calculate(self):
        print 'Processing all {} phases...'.format(len(self.trainingLog.phases))
        for phase in self.trainingLog.phases:
            activity=phase['activity']
            print '  {}/{}/{} {}'.format(phase['year'], phase['month'], phase['day'], activity)
            if activity == 'sick':
                self.sickDays.add(phase.get('date'))
            else:
                self.daysWorthIt.add(phase.get('date'))
                if activity not in self.activityTypes:
                    self.activityTypes.add(activity)
                    self.activities[activity] = LifetimeActivityTotal()

                if phase['year'] not in self.yearToActivityToTotalKm:
                    self.yearToActivityToTotalKm[phase['year']]={}
                    self.yearToActivityToTotalKm[phase['year']]['weight-min']=1024.0
                    self.yearToActivityToTotalKm[phase['year']]['weight-max']=0.0
                if phase['activity'] not in self.yearToActivityToTotalKm[phase['year']]:
                    self.yearToActivityToTotalKm[phase['year']][phase['activity']]={'distance': 0.0, 'time': 0}

                if phase['year'] not in self.yearToMonthToActivityToKmTimeWeight:
                    self.yearToMonthToActivityToKmTimeWeight[phase['year']]={}
                if phase['month'] not in self.yearToMonthToActivityToKmTimeWeight[phase['year']]:
                    self.yearToMonthToActivityToKmTimeWeight[phase['year']][phase['month']]={}
                    self.yearToMonthToActivityToKmTimeWeight[phase['year']][phase['month']]['weight-min']=1024.0
                    self.yearToMonthToActivityToKmTimeWeight[phase['year']][phase['month']]['weight-max']=0.0
                if phase['activity'] not in self.yearToMonthToActivityToKmTimeWeight[phase['year']][phase['month']]:
                    self.yearToMonthToActivityToKmTimeWeight[phase['year']][phase['month']][phase['activity']]={'distance': 0.0, 'time': 0}

                if phase['year'] not in self.yearToWeekNumberToActivityToKmTimeWeight:
                    self.yearToWeekNumberToActivityToKmTimeWeight[phase['year']]={}
                weeknumber=date(int(phase['year']), int(phase['month']), int(phase['day'])).isocalendar()[1]
                if weeknumber not in self.yearToWeekNumberToActivityToKmTimeWeight[phase['year']]:
                    self.yearToWeekNumberToActivityToKmTimeWeight[phase['year']][weeknumber]={}
                    self.yearToWeekNumberToActivityToKmTimeWeight[phase['year']][weeknumber]['weight-min']=1024.0
                    self.yearToWeekNumberToActivityToKmTimeWeight[phase['year']][weeknumber]['weight-max']=0.0
                if phase['activity'] not in self.yearToWeekNumberToActivityToKmTimeWeight[phase['year']][weeknumber]:
                    self.yearToWeekNumberToActivityToKmTimeWeight[phase['year']][weeknumber][phase['activity']]={'distance': 0.0, 'time': 0}

                if 'distance' in phase:
                    # TODO calculate km once
                    self.yearToActivityToTotalKm[phase['year']][phase['activity']]['distance']+=self.distanceFieldToKm(phase['distance'])
                    self.yearToMonthToActivityToKmTimeWeight[phase['year']][phase['month']][phase['activity']]['distance']+=self.distanceFieldToKm(phase['distance'])
                    self.yearToWeekNumberToActivityToKmTimeWeight[phase['year']][weeknumber][phase['activity']]['distance']+=self.distanceFieldToKm(phase['distance'])
                if 'time' in phase:
                    # TODO calculate secs once
                    self.yearToActivityToTotalKm[phase['year']][phase['activity']]['time']+=MslTime(phase['time']).getSeconds()
                    self.yearToMonthToActivityToKmTimeWeight[phase['year']][phase['month']][phase['activity']]['time']+=MslTime(phase['time']).getSeconds()
                    self.yearToWeekNumberToActivityToKmTimeWeight[phase['year']][weeknumber][phase['activity']]['time']+=MslTime(phase['time']).getSeconds()
                if 'weight' in phase:
                    self.yearToActivityToTotalKm[phase['year']]['weight-min']=min(self.weightFieldToKg(phase['weight']),self.yearToActivityToTotalKm[phase['year']]['weight-min'])
                    self.yearToActivityToTotalKm[phase['year']]['weight-max']=max(self.weightFieldToKg(phase['weight']),self.yearToActivityToTotalKm[phase['year']]['weight-max'])
                    self.yearToMonthToActivityToKmTimeWeight[phase['year']][phase['month']]['weight-min']=min(self.weightFieldToKg(phase['weight']),self.yearToMonthToActivityToKmTimeWeight[phase['year']][phase['month']]['weight-min'])
                    self.yearToMonthToActivityToKmTimeWeight[phase['year']][phase['month']]['weight-max']=max(self.weightFieldToKg(phase['weight']),self.yearToMonthToActivityToKmTimeWeight[phase['year']][phase['month']]['weight-max'])
                    self.yearToWeekNumberToActivityToKmTimeWeight[phase['year']][weeknumber]['weight-min']=min(self.weightFieldToKg(phase['weight']),self.yearToWeekNumberToActivityToKmTimeWeight[phase['year']][weeknumber]['weight-min'])
                    self.yearToWeekNumberToActivityToKmTimeWeight[phase['year']][weeknumber]['weight-max']=max(self.weightFieldToKg(phase['weight']),self.yearToWeekNumberToActivityToKmTimeWeight[phase['year']][weeknumber]['weight-max'])
        print '\nTotals (km) per year per activity:'
        print self.yearToActivityToTotalKm
        print '\nTotals (km/time/weight) per year per MONTH per activity:'
        print self.yearToMonthToActivityToKmTimeWeight
        print '\nTotals (km/time/weight) per year per WEEK per activity:'
        print self.yearToWeekNumberToActivityToKmTimeWeight

    # For every piece of equipment evaluate how much 1km cost
    def equipmentCostPerKm(self):
        print 'TBD'

    # For every piece of equipment evaluate how much 1day
    # of ownership cost
    def equipmentCostPerDay(self):
        print 'TBD'

    def byTimeTracksPerActivity(self):
        print 'TBD'
    def byDistanceTracksPerActivity(self):
        print 'TBD'
    def racesPerActivity(self):
        print 'TBD'

    def meDistancePerDayPerActivity(self):
        print 'TBD'
    def meDistancePerDayAllActivities(self):
        print 'TBD'
    def meTotalUnitsForEachActivity(self):
        print 'TBD'

#
# HTML rendering
#

css='''\
/* My Sport Life CSS

 Web 2.0 colors:
  Shiny silver [#EEEEEE]
  Reddit white [#FFFFFF]
  Magnolia Mag.nolia [#F9F7ED]
  Interactive action yellow [#FFFF88]
  Qoop Mint [#CDEB8B]
  Gmail blue [#C3D9FF]
  Shadows Grey [#36393D]
  Mozilla Red [#FF1A00]
  Rollyo Red [#CC0000]
  RSS Orange [#FF7400]
  Techcrunch green [#008C00]
  Newsvine Green [#006E2E]
  Flock Blue [#4096EE]
  Flickr Pink [#FF0084]
  Ruby on Rails Red [#B02B2C]
  Etsy Vermillion [#D15600]
  43 Things Gold [#C79810]
  Writely Olive [#73880A]
  Basecamp Green [#6BBA70]
  Mozilla Blue [#3F4C6B]
  Digg Blue [#356AA0]
  Last.fm Crimson [#D01F3C]
*/

html {
    margin: 0px;
    padding: 0px;
}

body {
    margin: 0px;
    padding: 0px;
    font-family: 'Roboto', sans-serif;
    font-size: 70%;
    background: #000;
    color: #fff;
}

a:link {
  text-decoration: none;
  border-bottom: 1px dotted #aaa;
  color: #fff;
}
a:visited {
  text-decoration: none;
  color: #fff;
}
a:active {
  text-decoration: none;
  color: #fff;
}
a:hover {
  border-bottom: 1px solid #aaa;
  text-decoration: none;
  color: #fff;
}

.msl-mainContainer {
    width: 100%;
}

.msl-lifeTitle {
    font-size: xx-large;
    width: 100%;
    text-align: center;
}

.msl-footer {
    width: 100%;
    text-align: center;
}

/* activities: colors */

.msl-activityRunning {
  background-color: #0066ff;
}
.msl-activityBiking {
  background-color: #006600;
}
.msl-activityConcept2 {
  background-color: #fff;
}
.msl-activitySwimming {
  background-color: #0000ff;
}

/* container: left - menu */

/* container: right */
.msl-rightMainPaneContainer {
  vertical-align: top;
  text-align: center;
}

/* summary */

.msl-tableSummaryLifetime {
  margin-left: auto;
  margin-right: auto;
}

/* year: chart monthly */
.msl-chartYearPageKmMonthly {
  background-color: #000;
  text-align: center;
  margin-left: auto;
  margin-right: auto;
}
.msl-chartYearPageKmMonthlyMonth {
  vertical-align: top;
  text-align: center;
}
.msl-chartYearPageKmMonthlyMonthSegment {
  width: 15px;
}

/* year: chart weekly km */
.msl-chartYearPageKmWeekly {
  background-color: #000;
  margin-left: auto;
  margin-right: auto;
}
.msl-chartYearPageKmWeeklyWeekSegment {
  width: 5px;
}

/* year: chart weekly weight */
.msl-chartYearPageWeightWeekly {
  background-color: #000;
}
.msl-chartYearPageWeightWeeklySegment {
  width: 5px;
  background-color: #aaa;
}

/* year: training calendar */
.msl-yearPageTrainingCalendar {
  vertical-align: top;
  border: 1px solid #222;
  border-collapse: collapse;
  margin-left: auto;
  margin-right: auto;
}
.msl-yearPageTrainingCalendar > tbody > tr > td+td {
  border-left: 1px solid #222;
  border-bottom: 1px solid #222;
}

.msl-calendarSickPhase {
  background-color: #e00;
}
.msl-calendarSauna {
  background-color: #993300;
}
.msl-calendarRacePhase {
  background-color: #e00;
}
.msl-calendarRunningRegenerationPhase {
  background-color: #aaa;
}
.msl-calendarRunningSpeedPhase {
  background-color: #aaa;
}
.msl-calendarRunningTempoPhase {
  background-color: #aaa;
}
.msl-calendarRunningHillsPhase {
  background-color: #aaa;
}
.msl-calendarRunningFartlekPhase {
  background-color: #aaa;
}
.msl-calendarRunningLongPhase {
  background-color: #aaa;
}
.msl-calendarConcept2Phase {
  background-color: #aaa;
}
.msl-calendarConcept2LowSpmPhase {
  background-color: #aaa;
}
.msl-calendarRowingOnWaterPhase {
  background-color: #aaa;
}
.msl-calendarKayakOnWaterPhase {
  background-color: #aaa;
}
.msl-calendarBikingMtbPhase {
  background-color: #006600;
}
.msl-calendarBodyweightExercisePhase {
  background-color: #990099;
}
.msl-calendarWeightliftingPhase {
  background-color: #000099;
}

.msl-notThisYearDay {
  background-color: #222;
}

/* eof */
'''

htmlPagePrefix='''\
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>{} - My Sport Life</title>
    <meta name="description" content="MySportLife is a training log with advanced reporting and analytics."/>
    <meta name="keywords" content="training, log, running, rowing, biking, swimming"/>
    <link href='./style.css' rel='stylesheet' type='text/css'>
    <link rel="shortcut icon" href="./favicon.ico" />
    <link rel="alternate" type="application/atom+xml" title="MySportLife commits on GitHub" href="https://github.com/dvorka/my-sport-life/commits/master.atom">
    <link href='http://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>
  </head>
<body>

<table class="msl-mainContainer">
  <tr>
'''

htmlLeftMenuPanePrefix='''
    <!-- left menu -->
    <td class="msl-leftMenubarContainer" valign="top">
      <div title="My Sport Life" style="color: #555; height: 50px; font-size: xx-large; text-align: center;"><a style="color: #555;" href="http://www.github.com/dvorka/my-sport-life">MSF</a></div>
      <table class="msl-leftMenuBar">
        <tr><td title="Name, age, equipment, injuries, per ? statistics, motto, photo, ..."><a href="./profile.html">Me</a></td></tr>
        <tr><td><a href="./index.html">Summary</a></td></tr>
        <tr><td><a href="./statistics.html">Statistics</a></td></tr>
        <tr><td><a href="./equipment.html">Equipment</a></td></tr>
        <tr><td><a href="./weight.html">Weight</a></td></tr>
        <tr>
          <td>
            Years:
            <table style="margin-left: 7px">
'''

htmlLeftMenuReports='''
        <tr>
          <td title="Personal Bests">
            PBs:
            <table style="margin-left: 7px">
              <tr><td><a href="./pb-running.html">Running</a></td></tr>
              <tr><td><a href="./pb-concept2.html">Concept2</a></td></tr>
              <tr><td><a href="./pb-mtb.html">MTB</a></td></tr>
            </table>
          </td>
        </tr>
        <tr>
          <td title="Races">
            Races:
            <table style="margin-left: 7px">
              <tr><td><a href="./races-running.html">Running</a></td></tr>
            </table>
          </td>
        </tr>
        <tr>
          <td>
            Phases/km:
            <table style="margin-left: 7px">
            {}
            </table>
          </td>
        </tr>
        <tr>
          <td>
            Phases/time:
            <table style="margin-left: 7px">
              {}
            </table>
          </td>
        </tr>
'''

htmlLeftMenuPaneSuffix='''
      </table>
    </td>
'''

htmlMainPanePrefix='''\
    <td class="msl-rightMainPaneContainer">
'''

htmlPageTitle='''      <div class="msl-lifeTitle">{}</div>'''

#
# ... here comes page body specific for every page ...
#

htmlMainPaneSuffix='''\
    <td/>
  </tr>
'''

htmlPageSuffix='''
  <tr>
    <td colspan="2">
      <div class="msl-footer">
        <a href="http://www.mindforger.com">mindforger.com</a>
        <br>2015
        <br>(cc)
        <br>Generated: {}/{}/{} {}:{}.{}
      </div>
    <td>
  </tr>
</table>

</body>
</html>
'''

#
# Page: All years summary
#

htmlAllYearsSummaryTablePrefix='''
    <table>
    <tr>
      <td>Total</td>
      <td>Running</td>
      <td>Biking</td>
      <td>Rowing</td>
      <td>Skiing</td>
      <td>Swimming</td>
    </tr>
'''

htmlAllYearsSummaryTableSuffix='''
    </table>
'''

#
# Page: Activity by distance
#

class HtmlLogGenerator:

    def __init__(self, targetDirectoryPath, report):
        self.targetDirectoryPath = targetDirectoryPath
        self.report = report

    def generate(self):
        print '\nBuilding HTML site...'
        self.clean()
        self.generateFileCss()
        self.generateFileIndex()
        for year in self.report.trainingLog.yearToPhases.keys():
            self.generateFileForYear(year)
        for activity in self.report.activityTypes:
            self.generateFileByDistance(activity)

    def clean(self):
        if os.path.isdir(self.targetDirectoryPath) and os.path.exists(self.targetDirectoryPath):
            rmDirRecursively(self.targetDirectoryPath)
        os.mkdir(self.targetDirectoryPath)

    def generateFileCss(self):
        filePath = self.targetDirectoryPath+'/style.css'
        f = open(filePath, "w")
        f.write(css)
        f.close()

    def writePageEnd(self, f):
        f.write(htmlMainPaneSuffix)
        f.write(htmlPageSuffix.format(datetime.today().year, datetime.today().month, datetime.today().day, datetime.today().hour, datetime.today().minute, datetime.today().second))

    def generateFileIndex(self):
        filePath = self.targetDirectoryPath+'/index.html'
        print 'Generating {}...'.format(filePath)
        f = open(filePath, "w")
        f.write(htmlPagePrefix.format('Summary'))
        self.writeLeftMenu(f)
        f.write(htmlMainPanePrefix)
        f.write(htmlPageTitle.format('Summary'))
        # begin body

        self.writeAllYearsSummaryTable(f)
        # TODO per year additive chart
        # TODO per year summary table
        # TODO statistics
        # TODO list of links to report

        # end body
        self.writePageEnd(f)
        f.close()

    def generateFileForYear(self, year):
        filePath = self.targetDirectoryPath+'/year-'+str(year)+'.html'
        print 'Generating {}...'.format(filePath)
        f = open(filePath, "w")
        f.write(htmlPagePrefix.format(year))
        self.writeLeftMenu(f)
        f.write(htmlMainPanePrefix)
        f.write(htmlPageTitle.format(year))
        # begin body
        self.writeByMonthChartForYear(f,year)
        # end body
        self.writePageEnd(f)
        f.close()

    def writeActivitiesChartColumnForMonth(self, year, month):
        if year in self.report.yearToMonthToActivityToKmTimeWeight:
            for activity in self.report.yearToMonthToActivityToKmTimeWeight[year]:
                if 'distance' in self.report.yearToMonthToActivityToKmTimeWeight[year][activity]:
                    km=self.report.yearToMonthToActivityToKmTimeWeight[year][activity]['distance']
                    height=self.report.yearToMonthToActivityToKmTimeWeight[year][activity]['distance']
                    result='<div title="{}: {}km" class="msl-chartYearPageKmMonthlyMonthSegment msl-activityRunning" style="height: {}px;"></div>'.format(activity,km,height)
                    #              <div title="Concept2: 44km" class="msl-chartYearPageKmMonthlyMonthSegment msl-activityConcept2" style="height: 5px;"></div>
                    #              <div title="Biking: 85km" class="msl-chartYearPageKmMonthlyMonthSegment msl-activityBiking" style="height: 5px;"></div>
                    return result
        return '...'

    def writeWeightChartColumnForMonth(self, year, month):
        # TODO self.report.getMinWeight(year,m)
        # min weight, max weight, chart showing min/max delta (green/red if I was getting fat/slimming)
        return 'TBD'.format(month)

    def writeByMonthChartForYear(self, f, year):
        f.write('\n       <table class="msl-chartYearPageKmMonthly">')
        # activities split columns chart
        f.write('\n         <tr>')
        f.write('\n           ')
        for month in range(1,12):
            f.write('\n           <td valign="bottom" align="center">{}</td>'.format(self.writeActivitiesChartColumnForMonth(year,month)))
        f.write('\n         </tr>')
        # month total
        f.write('\n         <tr>')
        f.write('\n           ')
        for month in range(1,12):
            # TODO f.write('<td>{}</td>'.format(self.report.getTotalForMonth(year,m)))
            f.write('<td>123</td>')
            pass
        f.write('\n         </tr>')
        # month name
        f.write('\n         <tr>')
        f.write('\n           ')
        for month in l10nmonths:
            f.write('<td>{}</td>'.format(month))
        f.write('\n         </tr>')
        # weight min
        f.write('\n         <tr>')
        f.write('\n           ')
        for month in range(1,12):
            # valign="bottom" align="center"
            # TODO f.write('<td>{}</td>'.format(self.report.getTotalForMonth(year,m)))
            f.write('<td>85.4</td>')
            pass
        f.write('\n         </tr>')
        # weight chart
        f.write('\n         <tr>')
        f.write('\n           ')
        for month in range(1,12):
            f.write('<td>{}</td>'.format(self.writeWeightChartColumnForMonth(year, month)))
        f.write('\n         </tr>')
        f.write('\n       </table>')

    def generateFileByDistance(self, activity):
        filePath = self.targetDirectoryPath+'/phases-by-distance-'+activity.lower()+'.html'
        print 'Generating {}...'.format(filePath)
        f = open(filePath, "w")
        f.write(htmlPagePrefix.format(activity+' by Distance'))
        self.writeLeftMenu(f)
        f.write(htmlMainPanePrefix)
        f.write(htmlPageTitle.format(activity+' by Distance'))
        # begin main
        phasesByDistance=self.report.getPhasesByDistanceForActivity(activity)
        f.write("\n      <table>")
        for phase in phasesByDistance:
            f.write('\n          <tr>')
            if "distance" in phase:
                f.write('<td>{}</td>'.format(phase["distance"]))
            else:
                print '  Warning: no distance in phase {}/{}'.format(phase['year'], phase["date"])
                f.write('<td>0km</td>')
            if "time" in phase:
                f.write('<td>{}</td>'.format(phase["time"]))
            else:
                f.write("<td>00h00'0</td>")
            if "track" in phase:
                f.write('<td>{}</td>'.format(phase["track"]))
            else:
                f.write('<td>-</td>')
            f.write('<td>{}/{}/{}</td>'.format(phase["year"], phase["month"], phase["day"]))
            f.write('<td>{}</td>'.format(phase["description"]))
            f.write('</tr>')
        f.write("\n      </table>")
        # end main
        self.writePageEnd(f)
        f.close()

    def writeAllYearsSummaryTable(self, f):
        f.write('\n      <table>')
        f.write('\n        <tr>')
        for activityType in self.report.activityTypes:
            f.write('\n          <th>{}</th>'.format(activityType))
        f.write('\n        </tr>')
        f.write('\n        <tr>')
        for activityType in self.report.activityTypes:
            f.write('\n          <td>{}</td>'.format(self.report.activities.get(activityType).km))
        f.write('\n        </tr>')
        f.write('\n      </table>')

    def writeLeftMenu(self, f):
        f.write(htmlLeftMenuPanePrefix)
        for year in self.report.trainingLog.yearToPhases.keys():
            f.write('\n              <tr><td><a href="./year-{}.html">{}</a></td></tr>'.format(year, year))
        f.write('\n            </table>')
        f.write('\n          </td>')
        f.write('\n        </tr>')
        htmlActivitiesByKm=''
        htmlActivitiesByTime=''
        for activityType in self.report.activityTypes:
            htmlActivitiesByKm=htmlActivitiesByKm+'\n         <tr><td><a href="./phases-by-distance-'+activityType.lower()+'.html">'+activityType+'</a></td></tr>'
            htmlActivitiesByTime=htmlActivitiesByTime+'\n         <tr><td><a href="./phases-by-time-'+activityType.lower()+'.html">'+activityType+'</a></td></tr>'
        f.write(htmlLeftMenuReports.format(htmlActivitiesByKm, htmlActivitiesByTime))
        f.write(htmlLeftMenuPaneSuffix)

#
# tests
#

def testMslTime():
    testTimes=["1h","5'","5'10", "5'10.7", "13","1h10'","1h10'5","1h10'6.7"]
    for s in testTimes:
        mslTime=MslTime(s)
        print s+' -> '+str(mslTime.getSeconds())

#
# main()
#

#mySportLife = MySportLife('/home/dvorka/p/my-sport-life/github/my-sport-life/test/test-data','/home/dvorka/tmp/20years')
mySportLife = MySportLife('/home/dvorka/p/my-sport-life/github/my-sport-life/examples/20-years','/home/dvorka/tmp/20years')
mySportLife.generate()

# eof

redpajama_set_name: RedPajamaGithub


text:
package com.microsoft.azure.management.network.implementation;

import com.microsoft.azure.SubResource;
import com.microsoft.azure.management.apigeneration.LangDefinition;
import com.microsoft.azure.management.network.LoadBalancerFrontend;
import com.microsoft.azure.management.network.LoadBalancerInboundNatRule;
import com.microsoft.azure.management.network.LoadBalancer;
import com.microsoft.azure.management.network.TransportProtocol;
import com.microsoft.azure.management.resources.fluentcore.arm.ResourceUtils;
import com.microsoft.azure.management.resources.fluentcore.arm.models.implementation.ChildResourceImpl;
import com.microsoft.azure.management.resources.fluentcore.utils.Utils;

/**
 *  Implementation for {@link LoadBalancerInboundNatRule}.
 */
@LangDefinition
class LoadBalancerInboundNatRuleImpl
    extends ChildResourceImpl<InboundNatRuleInner, LoadBalancerImpl, LoadBalancer>
    implements
        LoadBalancerInboundNatRule,
        LoadBalancerInboundNatRule.Definition<LoadBalancer.DefinitionStages.WithCreateAndInboundNatRule>,
        LoadBalancerInboundNatRule.UpdateDefinition<LoadBalancer.Update>,
        LoadBalancerInboundNatRule.Update {

    LoadBalancerInboundNatRuleImpl(InboundNatRuleInner inner, LoadBalancerImpl parent) {
        super(inner, parent);
    }

    // Getters

    @Override
    public String name() {
        return this.inner().name();
    }

    @Override
    public String backendNicIpConfigurationName() {
        if (this.inner().backendIPConfiguration() == null) {
            return null;
        } else {
            return ResourceUtils.nameFromResourceId(this.inner().backendIPConfiguration().id());
        }
    }

    @Override
    public int backendPort() {
        return Utils.toPrimitiveInt(this.inner().backendPort());
    }

    @Override
    public String backendNetworkInterfaceId() {
        if (this.inner().backendIPConfiguration() == null) {
            return null;
        } else {
            return ResourceUtils.parentResourceIdFromResourceId(this.inner().backendIPConfiguration().id());
        }
    }

    @Override
    public TransportProtocol protocol() {
        return this.inner().protocol();
    }

    @Override
    public int frontendPort() {
        return Utils.toPrimitiveInt(this.inner().frontendPort());
    }

    @Override
    public boolean floatingIpEnabled() {
        return this.inner().enableFloatingIP().booleanValue();
    }

    @Override
    public LoadBalancerFrontend frontend() {
        return this.parent().frontends().get(
                ResourceUtils.nameFromResourceId(
                        this.inner().frontendIPConfiguration().id()));
    }

    @Override
    public int idleTimeoutInMinutes() {
        return Utils.toPrimitiveInt(this.inner().idleTimeoutInMinutes());
    }

    // Fluent setters

    @Override
    public LoadBalancerInboundNatRuleImpl withBackendPort(int port) {
        this.inner().withBackendPort(port);
        return this;
    }

    @Override
    public LoadBalancerInboundNatRuleImpl withFloatingIpEnabled() {
        return withFloatingIp(true);
    }

    @Override
    public LoadBalancerInboundNatRuleImpl withFloatingIpDisabled() {
        return withFloatingIp(false);
    }

    @Override
    public LoadBalancerInboundNatRuleImpl withFloatingIp(boolean enabled) {
        this.inner().withEnableFloatingIP(enabled);
        return this;
    }

    @Override
    public LoadBalancerInboundNatRuleImpl withFrontendPort(int port) {
        this.inner().withFrontendPort(port);
        if (this.backendPort() == 0) {
            // By default, assume the same backend port
            return this.withBackendPort(port);
        } else {
            return this;
        }
    }

    @Override
    public LoadBalancerInboundNatRuleImpl withIdleTimeoutInMinutes(int minutes) {
        this.inner().withIdleTimeoutInMinutes(minutes);
        return this;
    }

    @Override
    public LoadBalancerInboundNatRuleImpl withProtocol(TransportProtocol protocol) {
        this.inner().withProtocol(protocol);
        return this;
    }

    @Override
    public LoadBalancerInboundNatRuleImpl withFrontend(String frontendName) {
        SubResource frontendRef = new SubResource()
                .withId(this.parent().futureResourceId() + "/frontendIPConfigurations/" + frontendName);
        this.inner().withFrontendIPConfiguration(frontendRef);
        return this;
    }

    // Verbs

    @Override
    public LoadBalancerImpl attach() {
        return this.parent().withInboundNatRule(this);
    }
}


text:
/* @author rich
 * Created on 16-May-2004
 *
 * This code is covered by a Creative Commons
 * Attribution, Non Commercial, Share Alike license
 * License
 */
package org.lsmp.djep.groupJep.groups;

import org.nfunk.jep.JEP;
import org.lsmp.djep.groupJep.interfaces.*;
/**
 * Possibly the quatonians, compleatly untested.
 *
 * @author Rich Morris
 * Created on 16-May-2004
 */
public class Quartonians extends Group implements RingI {

	public static class Quartonian extends Number {
		double x,y,z,w;
		public Quartonian(double x,double y,double z,double w){
			this.w = x; this.y = y; this.z=z; this.w=w;
		}
		public double doubleValue() {return x;}
		public float floatValue() {return (float) x;}
		public int intValue() {return (int) x;}
		public long longValue() {return (long) x;}
		// TODO pretty print so 0 + 0 i + 0 j + 1 k printed as k
		public String toString() {return ""+x+"+"+y+" i +"+z+" j +"+w+" k";
	//		StringBuffer sb = new StringBuffer();
	//		if(x!=0.0) sb.append(x);

		}
	}
	private Quartonian ZERO = new Quartonian(0,0,0,0);
	private Quartonian ONE = new Quartonian(1,0,0,0);
	private Quartonian I = new Quartonian(0,1,0,0);
	private Quartonian J = new Quartonian(0,0,1,0);
	private Quartonian K = new Quartonian(0,0,0,1);

	public Number getZERO() {return ZERO;}
	public Number getONE() {return ONE;	}

	public Number getInverse(Number num) {
		Quartonian q = (Quartonian) num;
		return new Quartonian(-q.x,-q.y,-q.z,-q.w);
	}

	public Number add(Number a, Number b) {
		Quartonian p = (Quartonian) a;
		Quartonian q = (Quartonian) b;
		return new Quartonian(p.x+q.x,p.y+q.y,p.z+q.z,p.w+q.w);
	}

	public Number sub(Number a, Number b) {
		Quartonian p = (Quartonian) a;
		Quartonian q = (Quartonian) b;
		return new Quartonian(p.x-q.x,p.y-q.y,p.z-q.z,p.w-q.w);
	}

	public Number mul(Number a, Number b) {
		Quartonian p = (Quartonian) a;
		Quartonian q = (Quartonian) b;
		return new Quartonian(
			p.x*q.x - p.y*q.y - p.z*q.z - p.w*q.w,
			p.x*q.y - p.y*q.x + p.z*q.w - p.w*q.z,
			p.x*q.z - p.y*q.w + p.z*q.x + p.w*q.y,
			p.x*q.w - p.y*q.z - p.z*q.y + p.w*q.x
			);
	}

	public boolean equals(Number a, Number b) {
		Quartonian p = (Quartonian) a;
		Quartonian q = (Quartonian) b;
		return (p.x==q.x)&&(p.y==q.y)&&(p.z==q.z)&&(p.w==q.w);
	}

	public Number valueOf(String s) {
		return new Quartonian(Double.parseDouble(s),0,0,0);
	}

	public void addStandardConstants(JEP j) {
		super.addStandardConstants(j);
		j.addConstant("i",I);
		j.addConstant("j",J);
		j.addConstant("k",K);
	}
	public String toString() {return "quaternions";}

}


text:
namespace Midway.Api.Models
{
    public class OnChangedMessage
    {
        public bool Changed { get; set; }
        public string Name { get; set; }
    }
}


text:
/* HostServ core functions
 *
 * (C) 2003-2016 Anope Team
 * Contact us at team@anope.org
 *
 * Please read COPYING and README for further details.
 *
 * Based on the original code of Epona by Lara.
 * Based on the original code of Services by Andy Church.
 */

#include "module.h"

class CommandHSGroup : public Command
{
	bool setting;

 public:
	void Sync(const NickAlias *na)
	{
		if (setting)
			return;

		if (!na || !na->HasVhost())
			return;

		setting = true;
		for (unsigned i = 0; i < na->nc->aliases->size(); ++i)
		{
			NickAlias *nick = na->nc->aliases->at(i);
			if (nick)
			{
				nick->SetVhost(na->GetVhostIdent(), na->GetVhostHost(), na->GetVhostCreator());
				FOREACH_MOD(OnSetVhost, (nick));
			}
		}
		setting = false;
	}

	CommandHSGroup(Module *creator) : Command(creator, "hostserv/group", 0, 0), setting(false)
	{
		this->SetDesc(_("Syncs the vhost for all nicks in a group"));
	}

	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
	{
		if (Anope::ReadOnly)
		{
			source.Reply(READ_ONLY_MODE);
			return;
		}

		NickAlias *na = NickAlias::Find(source.GetNick());
		if (na && source.GetAccount() == na->nc && na->HasVhost())
		{
			this->Sync(na);
			if (!na->GetVhostIdent().empty())
				source.Reply(_("All vhosts in the group \002%s\002 have been set to \002%s\002@\002%s\002."), source.nc->display.c_str(), na->GetVhostIdent().c_str(), na->GetVhostHost().c_str());
			else
				source.Reply(_("All vhosts in the group \002%s\002 have been set to \002%s\002."), source.nc->display.c_str(), na->GetVhostHost().c_str());
		}
		else
			source.Reply(HOST_NOT_ASSIGNED);

		return;
	}

	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
	{
		this->SendSyntax(source);
		source.Reply(" ");
		source.Reply(_("This command allows users to set the vhost of their\n"
				"CURRENT nick to be the vhost for all nicks in the same\n"
				"group."));
		return true;
	}
};

class HSGroup : public Module
{
	CommandHSGroup commandhsgroup;
	bool syncongroup;
	bool synconset;

 public:
	HSGroup(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
		commandhsgroup(this)
	{
		if (!IRCD || !IRCD->CanSetVHost)
			throw ModuleException("Your IRCd does not support vhosts");
	}

	void OnSetVhost(NickAlias *na) anope_override
	{
		if (!synconset)
			return;

		commandhsgroup.Sync(na);
	}

	void OnNickGroup(User *u, NickAlias *na) anope_override
	{
		if (!syncongroup)
			return;

		commandhsgroup.Sync(na);
	}

	void OnReload(Configuration::Conf *conf) anope_override
	{
		Configuration::Block *block = conf->GetModule(this);
		syncongroup = block->Get<bool>("syncongroup");
		synconset = block->Get<bool>("synconset");
	}
};

MODULE_INIT(HSGroup)


text:
namespace global_media_controls {

namespace {

constexpr int kAutoDismissTimerInMinutesDefault = 60;  // minutes

constexpr const char kAutoDismissTimerInMinutesParamName[] = "timer_in_minutes";

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class MediaNotificationClickSource {
  kMedia = 0,
  kPresentation,
  kMediaFling,
  kMaxValue = kMediaFling
};

// Returns the time value to be used for the auto-dismissing of the
// notifications after they are inactive.
// If the feature (auto-dismiss) is disabled, the returned value will be
// TimeDelta::Max() which is the largest int64 possible.
base::TimeDelta GetAutoDismissTimerValue() {
  if (!base::FeatureList::IsEnabled(media::kGlobalMediaControlsAutoDismiss))
    return base::TimeDelta::Max();

  return base::Minutes(base::GetFieldTrialParamByFeatureAsInt(
      media::kGlobalMediaControlsAutoDismiss,
      kAutoDismissTimerInMinutesParamName, kAutoDismissTimerInMinutesDefault));
}

}  // namespace

MediaSessionItemProducer::Session::Session(
    MediaSessionItemProducer* owner,
    const std::string& id,
    std::unique_ptr<MediaSessionNotificationItem> item,
    mojo::Remote<media_session::mojom::MediaController> controller)
    : owner_(owner), id_(id), item_(std::move(item)) {
  DCHECK(owner_);
  DCHECK(item_);

  SetController(std::move(controller));
}

MediaSessionItemProducer::Session::~Session() {
  // If we've been marked inactive, then we've already recorded inactivity as
  // the dismiss reason.
  if (is_marked_inactive_)
    return;

  RecordDismissReason(dismiss_reason_.value_or(
      GlobalMediaControlsDismissReason::kMediaSessionStopped));
}

void MediaSessionItemProducer::Session::MediaSessionInfoChanged(
    media_session::mojom::MediaSessionInfoPtr session_info) {
  is_playing_ =
      session_info && session_info->playback_state ==
                          media_session::mojom::MediaPlaybackState::kPlaying;

  // If we've started playing, we don't want the inactive timer to be running.
  if (is_playing_) {
    if (inactive_timer_.IsRunning() || is_marked_inactive_) {
      MarkActiveIfNecessary();
      RecordInteractionDelayAfterPause();
      inactive_timer_.Stop();
    }
    return;
  }

  // If the timer is already running, we don't need to do anything.
  if (inactive_timer_.IsRunning())
    return;

  last_interaction_time_ = base::TimeTicks::Now();
  StartInactiveTimer();
}

void MediaSessionItemProducer::Session::MediaSessionActionsChanged(
    const std::vector<media_session::mojom::MediaSessionAction>& actions) {
  bool is_audio_device_switching_supported =
      base::ranges::find(
          actions,
          media_session::mojom::MediaSessionAction::kSwitchAudioDevice) !=
      actions.end();
  if (is_audio_device_switching_supported !=
      is_audio_device_switching_supported_) {
    is_audio_device_switching_supported_ = is_audio_device_switching_supported;
    is_audio_device_switching_supported_callback_list_.Notify(
        is_audio_device_switching_supported_);
  }
}

void MediaSessionItemProducer::Session::MediaSessionPositionChanged(
    const absl::optional<media_session::MediaPosition>& position) {
  OnSessionInteractedWith();
}

void MediaSessionItemProducer::Session::OnRequestIdReleased() {
  // The request ID is released when the tab is closed.
  set_dismiss_reason(GlobalMediaControlsDismissReason::kTabClosed);
}

void MediaSessionItemProducer::Session::SetController(
    mojo::Remote<media_session::mojom::MediaController> controller) {
  if (controller.is_bound()) {
    observer_receiver_.reset();
    controller->AddObserver(observer_receiver_.BindNewPipeAndPassRemote());
    controller_ = std::move(controller);
  }
}

void MediaSessionItemProducer::Session::set_dismiss_reason(
    GlobalMediaControlsDismissReason reason) {
  DCHECK(!dismiss_reason_.has_value());
  dismiss_reason_ = reason;
}

void MediaSessionItemProducer::Session::OnSessionInteractedWith() {
  // If we're not currently tracking inactive time, then no action is needed.
  if (!inactive_timer_.IsRunning() && !is_marked_inactive_)
    return;

  MarkActiveIfNecessary();

  RecordInteractionDelayAfterPause();
  last_interaction_time_ = base::TimeTicks::Now();

  // Otherwise, reset the timer.
  inactive_timer_.Stop();
  StartInactiveTimer();
}

bool MediaSessionItemProducer::Session::IsPlaying() const {
  return is_playing_;
}

void MediaSessionItemProducer::Session::SetAudioSinkId(const std::string& id) {
  controller_->SetAudioSinkId(id);
}

base::CallbackListSubscription MediaSessionItemProducer::Session::
    RegisterIsAudioDeviceSwitchingSupportedCallback(
        base::RepeatingCallback<void(bool)> callback) {
  callback.Run(is_audio_device_switching_supported_);
  return is_audio_device_switching_supported_callback_list_.Add(
      std::move(callback));
}

// static
void MediaSessionItemProducer::Session::RecordDismissReason(
    GlobalMediaControlsDismissReason reason) {
  base::UmaHistogramEnumeration("Media.GlobalMediaControls.DismissReason",
                                reason);
}

void MediaSessionItemProducer::Session::StartInactiveTimer() {
  DCHECK(!inactive_timer_.IsRunning());

  // Using |base::Unretained()| here is okay since |this| owns
  // |inactive_timer_|.
  // If the feature is disabled, the timer will run forever, in order for the
  // rest of the code to continue running as expected.
  inactive_timer_.Start(
      FROM_HERE, GetAutoDismissTimerValue(),
      base::BindOnce(&MediaSessionItemProducer::Session::OnInactiveTimerFired,
                     base::Unretained(this)));
}

void MediaSessionItemProducer::Session::OnInactiveTimerFired() {
  // If the session has been paused and inactive for long enough, then mark it
  // as inactive.
  is_marked_inactive_ = true;
  RecordDismissReason(GlobalMediaControlsDismissReason::kInactiveTimeout);
  owner_->OnSessionBecameInactive(id_);
}

void MediaSessionItemProducer::Session::RecordInteractionDelayAfterPause() {
  base::TimeDelta time_since_last_interaction =
      base::TimeTicks::Now() - last_interaction_time_;
  base::UmaHistogramCustomTimes(
      "Media.GlobalMediaControls.InteractionDelayAfterPause",
      time_since_last_interaction, base::Minutes(1), base::Days(1), 100);
}

void MediaSessionItemProducer::Session::MarkActiveIfNecessary() {
  if (!is_marked_inactive_)
    return;
  is_marked_inactive_ = false;

  owner_->OnSessionBecameActive(id_);
}

MediaSessionItemProducer::MediaSessionItemProducer(
    mojo::Remote<media_session::mojom::AudioFocusManager> audio_focus_remote,
    mojo::Remote<media_session::mojom::MediaControllerManager>
        controller_manager_remote,
    MediaItemManager* item_manager,
    absl::optional<base::UnguessableToken> source_id)
    : audio_focus_remote_(std::move(audio_focus_remote)),
      controller_manager_remote_(std::move(controller_manager_remote)),
      item_manager_(item_manager),
      item_ui_observer_set_(this) {
  if (source_id.has_value()) {
    audio_focus_remote_->AddSourceObserver(
        *source_id, audio_focus_observer_receiver_.BindNewPipeAndPassRemote());

    audio_focus_remote_->GetSourceFocusRequests(
        *source_id,
        base::BindOnce(&MediaSessionItemProducer::OnReceivedAudioFocusRequests,
                       weak_ptr_factory_.GetWeakPtr()));
  } else {
    audio_focus_remote_->AddObserver(
        audio_focus_observer_receiver_.BindNewPipeAndPassRemote());

    audio_focus_remote_->GetFocusRequests(
        base::BindOnce(&MediaSessionItemProducer::OnReceivedAudioFocusRequests,
                       weak_ptr_factory_.GetWeakPtr()));
  }
}

MediaSessionItemProducer::~MediaSessionItemProducer() = default;

base::WeakPtr<media_message_center::MediaNotificationItem>
MediaSessionItemProducer::GetMediaItem(const std::string& id) {
  auto it = sessions_.find(id);
  return it == sessions_.end() ? nullptr : it->second.item()->GetWeakPtr();
}

std::set<std::string> MediaSessionItemProducer::GetActiveControllableItemIds() {
  return active_controllable_session_ids_;
}

bool MediaSessionItemProducer::HasFrozenItems() {
  return !frozen_session_ids_.empty();
}

void MediaSessionItemProducer::OnFocusGained(
    media_session::mojom::AudioFocusRequestStatePtr session) {
  const std::string id = session->request_id->ToString();

  // If we have an existing unfrozen item then this is a duplicate call and
  // we should ignore it.
  auto it = sessions_.find(id);
  if (it != sessions_.end() && !it->second.item()->frozen())
    return;

  mojo::Remote<media_session::mojom::MediaController> item_controller;
  mojo::Remote<media_session::mojom::MediaController> session_controller;

  controller_manager_remote_->CreateMediaControllerForSession(
      item_controller.BindNewPipeAndPassReceiver(), *session->request_id);
  controller_manager_remote_->CreateMediaControllerForSession(
      session_controller.BindNewPipeAndPassReceiver(), *session->request_id);

  if (it != sessions_.end()) {
    // If the notification was previously frozen then we should reset the
    // controller because the mojo pipe would have been reset.
    it->second.SetController(std::move(session_controller));
    it->second.item()->SetController(std::move(item_controller),
                                     std::move(session->session_info));
  } else {
    sessions_.emplace(
        std::piecewise_construct, std::forward_as_tuple(id),
        std::forward_as_tuple(
            this, id,
            std::make_unique<MediaSessionNotificationItem>(
                this, id, session->source_name.value_or(std::string()),
                std::move(item_controller), std::move(session->session_info)),
            std::move(session_controller)));

    for (auto& observer : observers_)
      observer.OnMediaSessionItemCreated(id);
  }
}

void MediaSessionItemProducer::OnFocusLost(
    media_session::mojom::AudioFocusRequestStatePtr session) {
  const std::string id = session->request_id->ToString();

  auto it = sessions_.find(id);
  if (it == sessions_.end())
    return;

  // If we're not currently showing this item, then we can just remove it.
  if (!base::Contains(active_controllable_session_ids_, id) &&
      !base::Contains(frozen_session_ids_, id)) {
    RemoveItem(id);
    return;
  }

  // Otherwise, freeze it in case it regains focus quickly.
  it->second.item()->Freeze(base::BindOnce(
      &MediaSessionItemProducer::OnItemUnfrozen, base::Unretained(this), id));
  active_controllable_session_ids_.erase(id);
  frozen_session_ids_.insert(id);
  item_manager_->OnItemsChanged();
}

void MediaSessionItemProducer::OnRequestIdReleased(
    const base::UnguessableToken& request_id) {
  const std::string id = request_id.ToString();
  auto it = sessions_.find(id);
  if (it == sessions_.end())
    return;

  // When the tab is closed, just remove the item instead of freezing it.
  it->second.OnRequestIdReleased();
  RemoveItem(id);
}

void MediaSessionItemProducer::OnMediaItemUIClicked(const std::string& id) {
  auto it = sessions_.find(id);
  if (it == sessions_.end())
    return;

  it->second.OnSessionInteractedWith();

  base::UmaHistogramEnumeration("Media.Notification.Click",
                                MediaNotificationClickSource::kMedia);

  it->second.item()->Raise();
}

void MediaSessionItemProducer::OnMediaItemUIDismissed(const std::string& id) {
  Session* session = GetSession(id);
  if (!session) {
    return;
  }

  session->set_dismiss_reason(
      GlobalMediaControlsDismissReason::kUserDismissedNotification);
  session->item()->Dismiss();
}

void MediaSessionItemProducer::AddObserver(
    MediaSessionItemProducerObserver* observer) {
  observers_.AddObserver(observer);
}

void MediaSessionItemProducer::RemoveObserver(
    MediaSessionItemProducerObserver* observer) {
  observers_.RemoveObserver(observer);
}

void MediaSessionItemProducer::OnItemShown(const std::string& id,
                                           MediaItemUI* item_ui) {
  if (item_ui)
    item_ui_observer_set_.Observe(id, item_ui);
}

bool MediaSessionItemProducer::IsItemActivelyPlaying(const std::string& id) {
  const auto it = sessions_.find(id);
  return it == sessions_.end() ? false : it->second.IsPlaying();
}

void MediaSessionItemProducer::HideItem(const std::string& id) {
  active_controllable_session_ids_.erase(id);
  frozen_session_ids_.erase(id);

  item_manager_->HideItem(id);
}

void MediaSessionItemProducer::RemoveItem(const std::string& id) {
  active_controllable_session_ids_.erase(id);
  frozen_session_ids_.erase(id);
  inactive_session_ids_.erase(id);

  for (auto& observer : observers_)
    observer.OnMediaSessionItemDestroyed(id);

  item_manager_->HideItem(id);
  sessions_.erase(id);
}

void MediaSessionItemProducer::ActivateItem(const std::string& id) {
  DCHECK(HasSession(id));
  if (base::Contains(inactive_session_ids_, id))
    return;

  active_controllable_session_ids_.insert(id);
  item_manager_->ShowItem(id);
}

bool MediaSessionItemProducer::HasSession(const std::string& id) const {
  return base::Contains(sessions_, id);
}

void MediaSessionItemProducer::LogMediaSessionActionButtonPressed(
    const std::string& id,
    media_session::mojom::MediaSessionAction action) {
  for (auto& observer : observers_)
    observer.OnMediaSessionActionButtonPressed(id, action);
}

void MediaSessionItemProducer::SetAudioSinkId(const std::string& id,
                                              const std::string& sink_id) {
  auto it = sessions_.find(id);
  DCHECK(it != sessions_.end());
  it->second.SetAudioSinkId(sink_id);
}

base::CallbackListSubscription
MediaSessionItemProducer::RegisterIsAudioOutputDeviceSwitchingSupportedCallback(
    const std::string& id,
    base::RepeatingCallback<void(bool)> callback) {
  auto it = sessions_.find(id);
  DCHECK(it != sessions_.end());

  return it->second.RegisterIsAudioDeviceSwitchingSupportedCallback(
      std::move(callback));
}

MediaSessionItemProducer::Session* MediaSessionItemProducer::GetSession(
    const std::string& id) {
  auto it = sessions_.find(id);
  return it == sessions_.end() ? nullptr : &it->second;
}

void MediaSessionItemProducer::OnSessionBecameActive(const std::string& id) {
  DCHECK(base::Contains(inactive_session_ids_, id));

  auto it = sessions_.find(id);
  DCHECK(it != sessions_.end());

  inactive_session_ids_.erase(id);

  if (it->second.item()->frozen()) {
    frozen_session_ids_.insert(id);
  } else {
    active_controllable_session_ids_.insert(id);
  }
  item_manager_->ShowItem(id);
}

void MediaSessionItemProducer::OnSessionBecameInactive(const std::string& id) {
  // If this session is already marked inactive, then there's nothing to do.
  if (base::Contains(inactive_session_ids_, id))
    return;

  inactive_session_ids_.insert(id);

  // Mark hidden on our end.
  HideItem(id);

  // Let the service know that the item is hidden.
  item_manager_->HideItem(id);
}

void MediaSessionItemProducer::HideMediaDialog() {
  item_manager_->HideDialog();
}

void MediaSessionItemProducer::OnReceivedAudioFocusRequests(
    std::vector<media_session::mojom::AudioFocusRequestStatePtr> sessions) {
  for (auto& session : sessions)
    OnFocusGained(std::move(session));
}

void MediaSessionItemProducer::OnItemUnfrozen(const std::string& id) {
  frozen_session_ids_.erase(id);

  active_controllable_session_ids_.insert(id);

  item_manager_->OnItemsChanged();
}

}  // namespace global_media_controls


text:
**Changes might happen in the future.**

**Markdown Preview Enhanced** allows you to render code output into documents.

    ```bash {cmd}
    ls .
    ```

    ```bash {cmd=true}
    ls .
    ```

    ```javascript {cmd="node"}
    const date = Date.now()
    console.log(date.toString())
    ```

> ⚠ **Script execution is off by default and needs to be explicitly enabled in Atom package / VSCode extension preferences**
>
> Please use this feature with caution because it may put your security at risk!
> Your machine can get hacked if someone makes you open a markdown with malicious code while script execution is enabled.
>
> Option name: `enableScriptExecution`

## Commands & Keyboard Shortcuts

- `Markdown Preview Enhanced: Run Code Chunk` or shift-enter
  execute single code chunk where your cursor is at.
- `Markdown Preview Enhanced: Run All Code Chunks` or ctrl-shift-enter
  execute all code chunks.

## Format

You can configure code chunk options in format of \`\`\`lang {cmd=your_cmd opt1=value1 opt2=value2 ...}.
When a value of an attribute is `true`, it can be omitted (e.g. `{cmd hide}` is identical to `{cmd=true hide=true}`).

**lang**
The grammar that the code block should highlight.
It should be put at the most front.

## Basic Options

**cmd**
The command to run.
If `cmd` is not provided, then `lang` will be regarded as command.

eg:

    ```python {cmd="/usr/local/bin/python3"}
    print("This will run python3 program")
    ```

**output**
`html`, `markdown`, `text`, `png`, `none`

Defines how to render code output.
`html` will append output as html.
`markdown` will parse output as markdown. (MathJax and graphs will not be supported in this case, but KaTeX works)
`text` will append output to a `pre` block.
`png` will append output as `base64` image.
`none` will hide the output.

eg:

    ```gnuplot {cmd=true output="html"}
    set terminal svg
    set title "Simple Plots" font ",20"
    set key left box
    set samples 50
    set style data points

    plot [-10:10] sin(x),atan(x),cos(atan(x))
    ```

![screen shot 2017-07-28 at 7 14 24 am](https://user-images.githubusercontent.com/1908863/28716734-66142a5e-7364-11e7-83dc-a66df61971dc.png)

**args**
args that append to command. eg:

    ```python {cmd=true args=["-v"]}
    print("Verbose will be printed first")
    ```

    ```erd {cmd=true args=["-i", "$input_file", "-f", "svg"] output="html"}
      # output svg format and append as html result.
    ```

**stdin**
If `stdin` is set to true, then the code will be passed as stdin instead of as file.

**hide**
`hide` will hide code chunk but only leave the output visible. default: `false`
eg:

    ```python {hide=true}
    print('you can see this output message, but not this code')
    ```

**continue**
If set `continue=true`, then this code chunk will continue from the last code chunk.
If set `continue=id`, then this code chunk will continue from the code chunk of id.
eg:

    ```python {cmd=true id="izdlk700"}
    x = 1
    ```

    ```python {cmd=true id="izdlkdim"}
    x = 2
    ```

    ```python {cmd=true continue="izdlk700" id="izdlkhso"}
    print(x) # will print 1
    ```

**class**
If set `class="class1 class2"`, then `class1 class2` will be add to the code chunk.

- `line-numbers` class will show line numbers to code chunk.

**element**
The element that you want to append after.
Check the **Plotly** example below.

**run_on_save** `boolean`
Run code chunk when the markdown file is saved. Default `false`.

**modify_source** `boolean`
Insert code chunk output directly into markdown source file. Default `false`.

**id**
The `id` of the code chunk. This option would be useful if `continue` is used.

## Macro

- **input_file**
  `input_file` is automatically generated under the same directory of your markdown file and will be deleted after running code that is copied to `input_file`.
  By default, it is appended at the very end of program arguments.
  However, you can set the position of `input_file` in your `args` option by `$input_file` macro. eg:

      ```program {cmd=true args=["-i", "$input_file", "-o", "./output.png"]}
      ...your code here
      ```

## Matplotlib

If set `matplotlib=true`, then the python code chunk will plot graphs inline in the preview.
eg:

    ```python {cmd=true matplotlib=true}
    import matplotlib.pyplot as plt
    plt.plot([1,2,3, 4])
    plt.show() # show figure
    ```

![screen shot 2017-07-28 at 7 12 50 am](https://user-images.githubusercontent.com/1908863/28716704-4009d43a-7364-11e7-9e46-889f961e5afd.png)

## LaTeX

Markdown Preview Enhanced also supports `LaTeX` compilation.
Before using this feature, you need to have [pdf2svg](extra.md?id=install-svg2pdf) and [LaTeX engine](extra.md?id=install-latex-distribution) installed.
Then you can simply write LaTeX in code chunk like this:

    ```latex {cmd=true}
    \documentclass{standalone}
    \begin{document}
      Hello world!
    \end{document}
    ```

![screen shot 2017-07-28 at 7 15 16 am](https://user-images.githubusercontent.com/1908863/28716762-8686d980-7364-11e7-9669-71138cb2e6e7.png)

### LaTeX output configuration

**latex_zoom**
If set `latex_zoom=num`, then the result will be scaled `num` times.

**latex_width**
The width of result.

**latex_height**
The height of result.

**latex_engine**
The latex engine that you used to compile `tex` file. By default `pdflatex` is used.

### TikZ example

It is recommended to use `standalone` while drawing `tikz` graphs.
![screen shot 2017-07-14 at 11 27 56 am](https://user-images.githubusercontent.com/1908863/28221069-8113a5b0-6887-11e7-82fa-23dd68f2be82.png)

## Plotly

Markdown Preview Enhanced allows you to draw [Plotly](https://plot.ly/) easily.
For example:
![screen shot 2017-10-20 at 10 41 25 am](https://user-images.githubusercontent.com/1908863/31829580-526a0c06-b583-11e7-82f2-09ea7a0b9672.png)

- The first line `@import "https://cdn.plot.ly/plotly-latest.min.js"` uses the [file import](file-imports.md) functionality to import `plotly-latest.min.js` file.
  However, it is recommended to download the js file to local disk for better performance.
- Then we created a `javascript` code chunk.

## Demo

This demo shows you how to render entity-relation diagram by using [erd](https://github.com/BurntSushi/erd) library.

    ```erd {cmd=true output="html" args=["-i", "$input_file" "-f", "svg"]}

    [Person]
    *name
    height
    weight
    +birth_location_id

    [Location]
    *id
    city
    state
    country

    Person *--1 Location
    ```

`erd {cmd=true output="html" args=["-i", "$input_file", "-f", "svg"]}`

- `erd` the program that we are using. (_you need to have the program installed first_)
- `output="html"` we will append the running result as `html`.
- `args` field shows the arguments that we will use.

Then we can click the `run` button at the preview to run our code.

![erd](https://user-images.githubusercontent.com/1908863/28221395-bcd0bd76-6888-11e7-8c6e-925e228d02cc.gif)

## Showcases (outdated)

**bash**
![Screen Shot 2016-09-24 at 1.41.06 AM](https://i.imgur.com/v5Y7juh.png)

**gnuplot with svg output**
![Screen Shot 2016-09-24 at 1.44.14 AM](https://i.imgur.com/S93g7Tk.png)

## Limitations

- Doesn't work with `ebook` yet.
- Might be buggy when using `pandoc document export`

[➔ Presentation](presentation.md)


text:
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

var xhr;
var ajaxModalMessagesQueue;
var twitter;

function showLogin()
{
    //$('#pannel_login').show();
    $('#loginModal').modal('show');
}

function showLoginAndClose()
{
    fermeMenuSmartphone();
    showLogin();
}

function ouvreMenuSmartphone(){
    $('#MenuMobile').show(250);
    $('.search-selector').css('z-index',97);
    $('.home-header-nav-close').on('click', function(event){
        event.preventDefault();
        fermeMenuSmartphone();
    });
}
function fermeMenuSmartphone(){
    $('#MenuMobile').hide(250);
    $('.search-selector').css('z-index',99);
}

function switchPanelHome(cible)
{
    $('.boxResearch .panelHome').hide();
    $('.boxResearch .'+cible).show(500);
    $('.boxResearchChoice a.active').removeClass('active');
    $(this).addClass('active');
}
function displayLoadingWheel() {
    return '';
}
function displayLoadingWheelFondBlanc() {
    return '';
}

function checkAjaxModal() {

    if (xhr && xhr.readystate != 4) {
        xhr.abort();
    }

    xhr = $.ajax({
        type: "POST",
        url: '/ajax/flashbags',
        dataType: "json",
        success: function (json)
        {
            ajaxModalMessagesQueue = new Array();
            // priorité 1 : les erreurs
            if (json.error.length > 0) {
                var messages = "";
                for (var i = 0; i < json.error.length; i++) {
                    messages += json.error[i] + '
';
                }
                ajaxModalMessagesQueue.push({'type': 'error', 'messages': messages});
            }
            // priorité 2 : les warnings
            if (json.warning.length > 0) {
                var messages = "";
                for (var i = 0; i < json.warning.length; i++) {
                    messages += json.warning[i] + '
';
                }
                ajaxModalMessagesQueue.push({'type': 'warning', 'messages': messages});
            }
            // priorité 3 : les notices
            if (json.notice.length > 0) {
                var messages = "";
                for (var i = 0; i < json.notice.length; i++) {
                    messages += json.notice[i] + '
';
                }
                ajaxModalMessagesQueue.push({'type': 'notice', 'messages': messages});
            }
            // priorité 4 : les succès
            if (json.success.length > 0) {
                var messages = "";
                for (var i = 0; i < json.success.length; i++) {
                    messages += json.success[i] + '
';
                }
                ajaxModalMessagesQueue.push({'type': 'success', 'messages': messages});
            }
            if (ajaxModalMessagesQueue.length > 0) {
                displayFlashModal(ajaxModalMessagesQueue[0]['type'], ajaxModalMessagesQueue[0]['messages']);
            }
        }
    });
    return false;
}
function displayFlashModal(typeMessage, message) {
    if (ajaxModalMessagesQueue.length > 0) {
        ajaxModalMessagesQueue.shift()
    }
    if ((typeMessage == 'success') || (typeMessage == 'notice')) {
        $('#flashBagModal').addClass('green');
    } else {
        $('#flashBagModal').removeClass('green');
    }
    if (typeMessage == 'success') {
        $('#flashBagModal h4').html('Confirmation');
        $('#flashBagModal .modal-body').html('
' + message + '
');
    }
    if (typeMessage == 'notice') {
        $('#flashBagModal h4').html('Information');
        $('#flashBagModal .modal-body').html('
' + message + '
');
    }
    if (typeMessage == 'warning') {
        $('#flashBagModal h4').html('Alerte');
        $('#flashBagModal .modal-body').html('
' + message + '
');
    }
    if (typeMessage == 'error') {
        $('#flashBagModal h4').html('Erreur');
        $('#flashBagModal .modal-body').html('
' + message + '
');
    }
    $('#flashBagModal .modal-body').append('
<button type="submit" class="btn submit" data-dismiss="modal">OK</button>
');

    $('#flashBagModal').modal('show');
}

$(document).on('hidden.bs.modal', '#flashBagModal', function () {
    if (ajaxModalMessagesQueue)
    {
        if (ajaxModalMessagesQueue.length > 0) {
            displayFlashModal(ajaxModalMessagesQueue[0]['type'], ajaxModalMessagesQueue[0]['messages']);
        }
    }
});

function ajaxRefreshHTML(url, target, data, modalId){
    if (typeof modalId === "undefined" || modalId === null) {
        modalId = "#myModal";
    }
    if (typeof data === "undefined" || data === null) {
        data = null;
    }
    $(modalId).empty().html(displayLoadingWheel());
    $(modalId).modal('show');
    $.ajax({
        type : 'POST',
        url : url,
        data : data,
        timeout : 20000,
        success : function(htmlResponse) {

            $(modalId).empty().html();
            $(modalId).modal('toggle');
            $(target).empty().html(htmlResponse);
            checkAjaxModal();

            //re-render the facebook icons (in a div with id of 'content')
            var idDom = target.substring(1);
            FB.XFBML.parse(document.getElementById(idDom));
            twttr.widgets.load();
        },
        error : function(jqXHR, textStatus, errorThrown) {
            $(modalId).empty().html('Erreur de traitement...');
            checkAjaxModal();
        }
    });
}

function ajaxRefreshHTMLResults(url, target, data, modalId){
    if (typeof modalId === "undefined" || modalId === null) {
        modalId = "#myModal";
    }
    if (typeof data === "undefined" || data === null) {
        data = null;
    }
    $(modalId).empty().html(displayLoadingWheel());
    $(modalId).modal('show');
    $.ajax({
        type : 'POST',
        url : url,
        data : data,
        timeout : 20000,
        success : function(htmlResponse) {

            $(modalId).empty().html();
            $(modalId).modal('toggle');
            $(target).empty().replaceWith(htmlResponse);

            if($(target).hasClass('bottle-list')){
                var total = $(target).attr('data-total-bottle');
                $('.search-results-wrapper .red.total-bottle').html(total);
                if(total>1){
                    $('.label-result-bottle-plural').html('s');
                }else{
                    $('.label-result-bottle-plural').empty();
                }
                var totalRef = $(target).attr('data-total-ref');
                $('.search-results-wrapper .red.total-ref').html(totalRef);
                if(totalRef>1){
                    $('.label-result-ref-plural').html('s');
                }else{
                    $('.label-result-ref-plural').empty();
                }
            }else if($(target).hasClass('swapper-list')){
                var totalTroqueur = $(target).attr('data-total-troqueur');
                $('.search-results-wrapper .red.total-troqueur').html(totalTroqueur);
                if(totalTroqueur>1){
                    $('.label-result-troqueur-plural').html('s');
                }else{
                    $('.label-result-troqueur-plural').empty();
                }
            }else {
                var total = $(target).attr('data-total');
                $('.search-results-wrapper .red').html(total);
                if(totalTroqueur>1){
                    $('.label-result-plural').html('s');
                }else{
                    $('.label-result-plural').empty();
                }
            }

            $('#panelInfoResultat').removeClass('hidden');

            checkAjaxModal();

            //re-render the facebook icons (in a div with id of 'content')
            var idDom = target.substring(1);
            FB.XFBML.parse(document.getElementById(idDom));
            if (typeof (twttr) != 'undefined') {
                twttr.widgets.load();
            } else {
                $.getScript('http://platform.twitter.com/widgets.js');
            }
        },
        error : function(jqXHR, textStatus, errorThrown) {
            $(modalId).empty().html('Erreur de traitement...');
            checkAjaxModal();
        }
    });
}

var map;
var map_tw;
var bigMap = [];
var bigMap_tw = [];
function initMap(){
    map = new google.maps.Map(document.getElementById('bigMap'), {
        center:{lat: 48.8589506, lng: 2.2773456},
        zoom: 16
    });
    map_tw = new google.maps.Map(document.getElementById('bigMap-tw'), {
        center:{lat: 48.8589506, lng: 2.2773456},
        zoom: 16
    });
}

function initialiseBigCarte(latitude, longitude, mapId){

    var latLng = {lat: Number(latitude.substring(0,10)), lng: Number(longitude.substring(0,9))};

    bigMap[mapId] = new google.maps.Map(document.getElementById('big-map-'+mapId), {
            center: latLng,
            zoom: 16,
            scrollwheel: false,
            zoomControl: true,
            zoomControlOptions: {
                    style: google.maps.ZoomControlStyle.LARGE
            }
    });

    var marker = new google.maps.Marker({
            position: latLng,
            map: bigMap[mapId]
    });

}

function getAddressForMap(url, id){
    var modalId = "#myModal";
    $(modalId).empty().html(displayLoadingWheel());
    $(modalId).modal('show');

    var data = {'id':id};

    $.ajax({
        type : 'POST',
        url : url,
        data : data,
        timeout : 20000,
        success : function(htmlResponse) {

            $(modalId).empty().html();
            $(modalId).modal('toggle');
            updateMapFromAddress(htmlResponse);
        },
        error : function(jqXHR, textStatus, errorThrown) {
            $(modalId).empty().html('Erreur de traitement...');
        }
    });
}
function updateMapFromAddress(address){
    var geocoder = new google.maps.Geocoder();
    geocoder.geocode( { 'address': address}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          map_tw.setCenter(results[0].geometry.location);
          var marker = new google.maps.Marker({
              map: map_tw,
              position: results[0].geometry.location
          });
        } else {
          alert("Geocode was not successful for the following reason: " + status);
        }
    });
}

function createCookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

function eraseCookie(name) {
	createCookie(name,"",-1);
}


text:
#include "asylo/platform/primitives/sgx/sgx_error_matchers.h"

#include <ostream>
#include <utility>

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "asylo/platform/primitives/sgx/sgx_errors.h"
#include "asylo/test/util/status_matchers.h"
#include "asylo/util/status.h"
#include "include/sgx_error.h"

namespace asylo {
namespace {

// A monomorphic Status matcher for SGX errors.
class SgxErrorMatcher : public ::testing::MatcherInterface<const Status &> {
 public:
  explicit SgxErrorMatcher(sgx_status_t sgx_status) : sgx_status_(sgx_status) {}

  void DescribeTo(std::ostream *os) const override {
    *os << "is an SGX error with error code " << DescribeSgxStatus(sgx_status_);
  }

  void DescribeNegationTo(std::ostream *os) const override {
    *os << "is not an SGX error with error code "
        << DescribeSgxStatus(sgx_status_);
  }

  bool MatchAndExplain(
      const Status &status,
      ::testing::MatchResultListener *listener) const override {
    sgx_status_t actual_error = GetSgxErrorCode(status);
    if (actual_error == SGX_SUCCESS) {
      *listener << "which is not an SGX error";
      return false;
    }
    if (actual_error != sgx_status_) {
      *listener << "which has SGX error code "
                << DescribeSgxStatus(actual_error);
      return false;
    }
    return true;
  }

 private:
  sgx_status_t sgx_status_;
};

}  // namespace

PolymorphicStatusMatcherType SgxErrorIs(sgx_status_t sgx_status) {
  return MakePolymorphicStatusMatcher(
      ::testing::MakeMatcher(new SgxErrorMatcher(sgx_status)));
}

}  // namespace asylo


text:
module RailsWorkflow
  # Default error resolver. Can be changed in configuration.
  # Manages errors processing
  class ErrorResolver
    attr_accessor :error
    delegate :update_attribute, :target, :operation, :process,
             :data, :can_restart_process?, to: :error

    def self.retry(error)
      new(error).retry
    end

    def initialize(error)
      @error = error
    end

    def retry
      update_attribute(:resolved, true)
      fix_status(error.parent)
      prepared_target.send(data[:method], *data[:args])
      try_restart_process unless target == 'process_manager'
    end

    def fix_status(subject)
      subject.status = Status::IN_PROGRESS
      subject.save
      fix_status(subject.parent) if subject.parent.present?
    end

    def prepared_target
      return operation_runner if target == 'operation_runner'
      return operation_builder if target == 'operation_builder'
      return dependency_resolver if target == 'dependency_resolver'
      return process_manager if target == 'process_manager'
      target
    end

    def try_restart_process
      return if process.nil? || process.status == Status::DONE
      process.update_attribute(:status, Status::IN_PROGRESS)

      process.reload
      process_runner.start if can_restart_process?
    end

    def config
      RailsWorkflow.config
    end

    def process_manager
      config.process_manager.new(process)
    end

    def operation_runner
      config.operation_runner.new(operation)
    end

    def operation_builder
      config.operation_builder.new(*data[:args]).tap { data[:args] = nil }
    end

    def dependency_resolver
      config.dependency_resolver.new(process)
    end

    def process_runner
      config.process_runner.new(process)
    end
  end
end


text:
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="MessageHandlerBase.cs" company="Kephas Software SRL">
//   Copyright (c) Kephas Software SRL. All rights reserved.
//   Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// <summary>
//   Provides a base implementation of a message handler.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Kephas.Messaging
{
    using System;
    using System.Threading;
    using System.Threading.Tasks;

    using Kephas;
    using Kephas.Diagnostics.Contracts;
    using Kephas.Logging;
    using Kephas.Messaging.Resources;
    using Kephas.Threading.Tasks;

    /// <summary>
    /// Provides a base implementation of a message handler.
    /// </summary>
    /// <typeparam name="TMessage">The message type.</typeparam>
    /// <typeparam name="TResponse">The response type.</typeparam>
    public abstract class MessageHandlerBase<TMessage, TResponse> : Loggable, IMessageHandler<TMessage>
        where TMessage : class
        where TResponse : class
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="MessageHandlerBase{TMessage, TResponse}"/> class.
        /// </summary>
        /// <param name="logManager">Manager for log.</param>
        protected MessageHandlerBase(ILogManager? logManager = null)
            : base(logManager)
        {
        }

        /// <summary>
        /// Processes the provided message asynchronously and returns a response promise.
        /// </summary>
        /// <param name="message">The message to be handled.</param>
        /// <param name="context">The processing context.</param>
        /// <param name="token">The cancellation token.</param>
        /// <returns>
        /// The response promise.
        /// </returns>
        public abstract Task<TResponse> ProcessAsync(TMessage message, IMessagingContext context, CancellationToken token);

        /// <summary>
        /// Processes the provided message asynchronously and returns a response promise.
        /// </summary>
        /// <param name="message">The message to be handled.</param>
        /// <param name="context">The processing context.</param>
        /// <param name="token">The cancellation token.</param>
        /// <returns>
        /// The response promise.
        /// </returns>
        async Task<IMessage?> IMessageHandler<TMessage>.ProcessAsync(TMessage message, IMessagingContext context, CancellationToken token)
        {
            Requires.NotNull(message, nameof(message));
            Requires.NotNull(context, nameof(context));

            this.Logger = this.GetLogger(context);
            var response = await this.ProcessAsync(message, context, token).PreserveThreadContext();
            return response.ToMessage();
        }

        /// <summary>
        /// Processes the provided message asynchronously and returns a response promise.
        /// </summary>
        /// <param name="message">The message to be handled.</param>
        /// <param name="context">The processing context.</param>
        /// <param name="token">The cancellation token.</param>
        /// <returns>
        /// The response promise.
        /// </returns>
        async Task<IMessage?> IMessageHandler.ProcessAsync(IMessage message, IMessagingContext context, CancellationToken token)
        {
            // typed message handlers register themselves for a message type which may not implement IMessage
            // therefore the actual processed message is the message content.
            var content = message.GetContent();
            var typedMessage = content as TMessage;
            if (typedMessage == null)
            {
                throw new ArgumentException(Strings.MessageHandler_BadMessageType_Exception.FormatWith(typeof(TMessage), content?.GetType()), nameof(message));
            }

            this.Logger = this.GetLogger(context);
            var response = await this.ProcessAsync(typedMessage, context, token).PreserveThreadContext();
            return response.ToMessage();
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources.
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
        }
    }
}


text:
@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    THSegmentedPager *pager = (THSegmentedPager *)((UINavigationController *)self.window.rootViewController).topViewController;
#ifndef LOAD_WITH_IDENTIFIERS
    NSMutableArray *pages = [NSMutableArray new];
    for (int i = 1; i < 4; i++) {
        // Create a new view controller and pass suitable data.
        SamplePagedViewController *pagedViewController = [pager.storyboard instantiateViewControllerWithIdentifier:@"SamplePagedViewController"];
        [pagedViewController setViewTitle:[NSString stringWithFormat:@"Page %d",i]];
        [pagedViewController.view setBackgroundColor:[UIColor colorWithHue:((i/8)%20)/20.0+0.02 saturation:(i%8+3)/10.0 brightness:91/100.0 alpha:1]];
        [pages addObject:pagedViewController];
    }
    [pager setPages:pages];
#else
    [pager setupPagesFromStoryboardWithIdentifiers:@[@"SamplePagedViewController",@"SamplePagedViewController",@"SamplePagedViewController"]];
#endif
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

@end


text:
"""
Setup script for the `proc` package.

**python setup.py install**
  Install from the working directory into the current Python environment.

**python setup.py sdist**
  Build a source distribution archive.

**python setup.py bdist_wheel**
  Build a wheel distribution archive.
"""

# Standard library modules.
import codecs
import os
import re

# De-facto standard solution for Python packaging.
from setuptools import find_packages, setup

def get_contents(*args):
    """Get the contents of a file relative to the source distribution directory."""
    with codecs.open(get_absolute_path(*args), 'r', 'UTF-8') as handle:
        return handle.read()

def get_version(*args):
    """Extract the version number from a Python module."""
    contents = get_contents(*args)
    metadata = dict(re.findall('__([a-z]+)__ = [\'"]([^\'"]+)', contents))
    return metadata['version']

def get_requirements(*args):
    """Get requirements from pip requirement files."""
    requirements = set()
    with open(get_absolute_path(*args)) as handle:
        for line in handle:
            # Strip comments.
            line = re.sub(r'^#.*|\s#.*', '', line)
            # Ignore empty lines
            if line and not line.isspace():
                requirements.add(re.sub(r'\s+', '', line))
    return sorted(requirements)

def get_absolute_path(*args):
    """Transform relative pathnames into absolute pathnames."""
    return os.path.join(os.path.dirname(os.path.abspath(__file__)), *args)

setup(
    name='proc',
    version=get_version('proc', '__init__.py'),
    description="Simple interface to Linux process information",
    long_description=get_contents('README.rst'),
    url='https://proc.readthedocs.io',
    author="Peter Odding",
    author_email='peter@peterodding.com',
    license='MIT',
    packages=find_packages(),
    test_suite='proc.tests',
    install_requires=get_requirements('requirements.txt'),
    entry_points=dict(console_scripts=[
        'cron-graceful = proc.cron:main',
        'notify-send-headless = proc.notify:main',
        'with-gpg-agent = proc.gpg:main',
        'with-gui-environment = proc.notify:with_gui_environment',
    ]),
    python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*',
    classifiers=[
        'Development Status :: 5 - Production/Stable',
        'Environment :: Console',
        'Intended Audience :: Developers',
        'Intended Audience :: Information Technology',
        'Intended Audience :: System Administrators',
        'License :: OSI Approved :: MIT License',
        'Operating System :: POSIX :: Linux',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.5',
        'Programming Language :: Python :: 3.6',
        'Programming Language :: Python :: 3.7',
        'Programming Language :: Python :: 3.8',
        'Programming Language :: Python :: Implementation :: CPython',
        'Programming Language :: Python :: Implementation :: PyPy',
        'Topic :: Software Development',
        'Topic :: Software Development :: Libraries :: Python Modules',
        'Topic :: System :: Operating System Kernels :: Linux',
        'Topic :: System :: Systems Administration',
        'Topic :: Terminals',
        'Topic :: Utilities',
    ])


text:
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

      <link rel="stylesheet" href="helpwin.css">
      <title>MATLAB File Help: lomb</title>

            MATLAB File Help: lomb
            View code for lomb
            WFDB Contents

lomb

function varargout=lomb(varargin)

 [Pxx,F]=lomb(x,dcOffset,smooth)

    Wrapper to WFDB LOMB:
         http://www.physionet.org/physiotools/wag/lomb-1.htm

 Transforms a real-valued time series 'x' into a power spectrum 'X', using a
 technique known as the Lomb periodogram. The input is a Nx2 matrix containing
 a sampled time series, presented as two columns of numbers (the sample times
 in the first column and the sample values in the second). The intervals between
 consecutive samples need not be uniform.

Input Parameters:
 x
       Nx2 vector of doubles. First column is sample time index (in
       seconds), and second column is the sample value of the signal at
       that time.

 dcOffset (Optional)
       Booelan. If present add constant to input samples ( x(:,2) ), such that the mean
       values of the time series is zero (default=1).

 smooth   (Optional)
       Boolean String specifying the if the output should be smoothed (default =1).

Output Parameters:

Pxx
       Mx1 Double. Estimated power spectrum.

F
       Mx1 Double. Frequency of the estimated power spectrum (Hz).

 CITING CREDIT: To credit this function, please cite the following paper at your work:

Moody, G.B.
    Spectral analysis of heart rate without resampling. Computers in Cardiology 1993, pp. 715-718 (IEEE Computer Society Press, 1993). http://www.physionet.org/physiotools/lomb/lomb.html .

Additional References:
Lomb, N.R.
    Least-squares frequency analysis of unequally spaced data. Astrophysics and Space Science 39:447-462 (1976).
Press, W.H, and Rybicki, G.B.
    Fast algorithm for spectral analysis of unevenly sampled data. Astrophysical J. 338:277-280 (1989).
Press, W.H. Teukolsky, S.A., Vetterling, W.T., and Flannery, B.P.
    Numerical Recipes in C: the Art of Scientific Computing, pp. 575-584 (Cambridge Univ. Press, 1992).
Moody, G.B.
    Spectral analysis of heart rate without resampling. Computers in Cardiology 1993, pp. 715-718 (IEEE Computer Society Press, 1993). http://www.physionet.org/physiotools/lomb/lomb.html .

 MATLAB wrapper written by Ikaro Silva, 2013
 Last Modified: -
 Version 1.0
 Since 0.9.0

 %Example: Heart Rate Spectral Analysis:
 [tm, signal]=rdsamp('mitdb/100',1);
 [ann]=rdann('mitdb/100','atr');
 [Pxx,F]=lomb([tm(ann) signal(ann)]);
 plot(F,Pxx);grid on;hold on

 See also RDANN, TACH, SQRS, WQRS