text:
import FactoryMaker from '../../core/FactoryMaker';
import X2JS from '../../../externals/xml2json';
import Debug from '../../core/Debug';

const SECONDS_IN_HOUR = 60 * 60; // Expression of an hour in seconds
const SECONDS_IN_MIN = 60; // Expression of a minute in seconds

function TTMLParser() {

    let context = this.context;
    let log = Debug(context).getInstance().log;

    /*
     * This TTML parser follows "EBU-TT-D SUBTITLING DISTRIBUTION FORMAT - tech3380" spec - https://tech.ebu.ch/docs/tech/tech3380.pdf.
     * */
    let instance,
        timingRegex,
        ttml, // contains the whole ttml document received
        ttmlStyling, // contains the styling information from the document (from head following EBU-TT-D)
        ttmlLayout, // contains the positioning information from the document (from head following EBU-TT-D)
        fontSize,
        lineHeight,
        linePadding,
        defaultLayoutProperties,
        defaultStyleProperties,
        fontFamilies,
        textAlign,
        multiRowAlign,
        wrapOption,
        unicodeBidi,
        displayAlign,
        writingMode,
        videoModel;

    let cueCounter = 0; // Used to give every cue a unique ID.

    function setConfig(config) {
        if (!config) return;

        if (config.videoModel) {
            videoModel = config.videoModel;
        }
    }

    /**
     * Get the begin-end interval if present, or null otherwise.
     *
     * @param {Object} element - TTML element which may have begin and end attributes
     */
    function getInterval(element) {
        if (element.hasOwnProperty('begin') && element.hasOwnProperty('end')) {
            let beginTime = parseTimings(element.begin);
            let endTime = parseTimings(element.end);
            return [beginTime, endTime];
        } else {
            return null;
        }
    }

    function getCueID() {
        let id = 'cue_TTML_' + cueCounter;
        cueCounter++;
        return id;
    }

    /*
    * Create list of intervals where spans start and end. Empty list if no times.
    * Clip to interval using startInterval and endInterval and add these two times.
    * Also support case when startInterval/endInteval not given (sideloaded file)
    *
    * @param {Array} spans - array of span elements
    */
    function createSpanIntervalList(spans, startInterval, endInterval) {

        let spanChangeTimes = [];
        let spanChangeTimeStrings = [];
        let cue_intervals = [];

        function addSpanTime(span, name) {
            if (span.hasOwnProperty(name)) {
                let timeString = span[name];
                if (spanChangeTimeStrings.indexOf(timeString) < 0) {
                    spanChangeTimeStrings.push(timeString);
                }
            }
        }

        for (let i = 0; i < spans.length; i++) {
            let span = spans[i];
            addSpanTime(span, 'begin');
            addSpanTime(span, 'end');
        }
        if (spanChangeTimeStrings.length === 0) {
            return cue_intervals; // No span timing so no intervals.
        }

        if (typeof startInterval !== 'undefined' && typeof endInterval !== 'undefined' ) {
            for (let i = 0; i < spanChangeTimeStrings.length; i++) {
                let changeTime = parseTimings(spanChangeTimeStrings[i]);
                if (startInterval < changeTime && changeTime < endInterval) {
                    spanChangeTimes.push(changeTime);
                }
            }
            spanChangeTimes.push(startInterval);
            spanChangeTimes.push(endInterval);
        } else {
            for (let i = 0; i < spanChangeTimeStrings.length; i++) {
                spanChangeTimes.push(parseTimings(spanChangeTimeStrings[i]));
            }
        }
        spanChangeTimes.sort(function (a, b) { return a - b;});
        for (let i = 0; i < spanChangeTimes.length - 1; i++) {
            cue_intervals.push([spanChangeTimes[i], spanChangeTimes[i + 1]]);
        }
        return cue_intervals;
    }

    function clipStartTime(startTime, intervalStart) {
        if (typeof startInterval !== 'undefined') {
            if (startTime < intervalStart) {
                startTime = intervalStart;
            }
        }
        return startTime;
    }

    function clipEndTime(endTime, intervalEnd) {
        if (typeof intervalEnd !== 'undefined') {
            if (endTime > intervalEnd) {
                endTime = intervalEnd;
            }
        }
        return endTime;
    }

    /*
     * Get interval from entity that has begin and end properties.
     * If intervalStart and intervalEnd defined, use them to clip the interval.
     * Return null if no overlap with interval
     */
    function getClippedInterval(entity, intervalStart, intervalEnd) {
        let startTime = parseTimings(entity.begin);
        let endTime = parseTimings(entity.end);
        startTime = clipStartTime(startTime, intervalStart);
        endTime = clipEndTime(endTime, intervalEnd);
        if (typeof intervalStart !== 'undefined' && typeof intervalEnd !== 'undefined') {
            if (endTime < intervalStart || startTime > intervalEnd) {
                log('TTML: Cue ' + startTime + '-' + endTime + ' outside interval ' +
                            intervalStart + '-' + intervalEnd);
                return null;
            }
        }
        return [startTime, endTime];
    }

    /*
     * Check if entity timing has some overlap with interval
     */
    function inIntervalOrNoTiming(entity, interval) {
        let inInterval = true;
        if (entity.hasOwnProperty('span')) {
            let entityInterval = getInterval(entity.span);
            if (entityInterval !== null) { //Timing
                inInterval = (entityInterval[0] < interval[1] && entityInterval[1] > interval[0]);
            }
        }
        return inInterval;
    }

    /**
     * Parse the raw data and process it to return the HTML element representing the cue.
     * Return the region to be processed and controlled (hide/show) by the caption controller.
     * @param {string} data - raw data received from the TextSourceBuffer
     * @param {number} intervalStart
     * @param {number} intervalEnd
     *
     */

    function parse(data, intervalStart, intervalEnd) {
        let tt, // Top element
            head, // head in tt
            body, // body in tt
            ttExtent, // extent attribute of tt element
            type;

        var errorMsg = '';

        let converter = new X2JS([], '', false);

        // Parse the TTML in a JSON object.
        ttml = converter.xml_str2json(data);

        if (!ttml) {
            throw new Error('TTML document could not be parsed');
        }

        if (videoModel.getTTMLRenderingDiv()) {
            type = 'html';
        }

        // Check the document and compare to the specification (TTML and EBU-TT-D).
        tt = ttml.tt;
        if (!tt) {
            throw new Error('TTML document lacks tt element');
        }

        // Get the namespace if there is one defined in the JSON object.
        var ttNS = getNamespacePrefix(tt, 'http://www.w3.org/ns/ttml');

        // Remove the namespace before each node if it exists:
        if (ttNS) {
            removeNamespacePrefix(tt, ttNS);
        }

        ttExtent = tt['tts:extent']; // Should check that tts is right namespace.

        head = tt.head;
        if (!head) {
            throw new Error('TTML document lacks head element');
        }
        if (head.layout) {
            ttmlLayout = head.layout.region_asArray; //Mandatory in EBU-TT-D
        }
        if (head.styling) {
            ttmlStyling = head.styling.style_asArray; // Mandatory in EBU-TT-D
        }
        body = tt.body;
        if (!body) {
            throw new Error('TTML document lacks body element');
        }

        // Extract the cellResolution information
        var cellResolution = getCellResolution();

        // Recover the video width and height displayed by the player.
        var videoWidth = videoModel.getElement().clientWidth;
        var videoHeight = videoModel.getElement().clientHeight;

        // Compute the CellResolution unit in order to process properties using sizing (fontSize, linePadding, etc).
        var cellUnit = [videoWidth / cellResolution[0], videoHeight / cellResolution[1]];
        defaultStyleProperties['font-size'] = cellUnit[1] + 'px;';

        var regions = [];
        if (ttmlLayout) {
            for (var i = 0; i < ttmlLayout.length; i++) {
                regions.push(processRegion(JSON.parse(JSON.stringify(ttmlLayout[i])), cellUnit));
            }
        }

        // Get the namespace prefix.
        var nsttp = getNamespacePrefix(ttml.tt, 'http://www.w3.org/ns/ttml#parameter');

        // Set the framerate.
        if (tt.hasOwnProperty(nsttp + ':frameRate')) {
            tt.frameRate = parseInt(tt[nsttp + ':frameRate'], 10);
        }
        var captionArray = [];
        // Extract the div
        var divs = tt.body_asArray[0].__children;

        // Timing is either on div, paragraph or span level.

        for (let k = 0; k < divs.length; k++) {
            let div = divs[k].div;
            let divInterval = null; // This is mainly for image subtitles.

            if (null !== (divInterval = getInterval(div))) {
                // Timing on div level is not allowed by EBU-TT-D.
                // We only use it for SMPTE-TT image subtitle profile.

                // Layout should be defined by a region. Given early test material, we also support that it is on
                // div level
                let layout;
                if (div.region) {
                    let region = findRegionFromID(ttmlLayout, div.region);
                    layout = getRelativePositioning(region, ttExtent);
                }
                if (!layout) {
                    layout = getRelativePositioning(div, ttExtent);
                }

                let images = tt.head.metadata.image_asArray; // TODO. Add URL image sources

                if (div['smpte:backgroundImage'] !== undefined) {
                    for (let j = 0; j < images.length; j++) {
                        if (('#' + images[j]['xml:id']) === div['smpte:backgroundImage']) {
                            captionArray.push({
                                start: divInterval[0],
                                end: divInterval[1],
                                id: getCueID(),
                                data: 'data:image/' + images[j].imagetype.toLowerCase() + ';base64, ' + images[j].__text,
                                type: 'image',
                                layout: layout
                            });
                        }
                    }
                }
                continue; // Next div
            }

            let paragraphs = div.p_asArray;
            // Check if cues is not empty or undefined.
            if (divInterval === null && (!paragraphs || paragraphs.length === 0)) {
                errorMsg = 'TTML has div that contains no timing and no paragraphs.';
                log(errorMsg);
                return captionArray;
            }

            for (let j2 = 0; j2 < paragraphs.length; j2++) {
                let paragraph = paragraphs[j2];
                let spans = paragraph.span_asArray;
                let cueIntervals = [];
                // For timing, the overall goal is to find the intervals where there should be cues
                // The timing may either be on paragraph or span level.
                if (paragraph.hasOwnProperty('begin') && paragraph.hasOwnProperty('end')) {
                    // Timing on paragraph level
                    let clippedInterval = getClippedInterval(paragraph, intervalStart, intervalEnd);
                    if (clippedInterval !== null) {
                        cueIntervals.push(clippedInterval);
                    }
                } else {
                    // Timing must be on span level
                    cueIntervals = createSpanIntervalList(spans, intervalStart, intervalEnd);
                }
                if (cueIntervals.length === 0) {
                    errorMsg = 'TTML: Empty paragraph';
                    continue; // Nothing in this paragraph
                }

                let paragraphChildren = paragraph.__children;

                for (let i2 = 0; i2 < cueIntervals.length; i2++) {
                    let interval = cueIntervals[i2];
                    let childrenInInterval = [];
                    for (let k2 = 0; k2 < paragraphChildren.length; k2++) {
                        let child = paragraphChildren[k2];
                        if (inIntervalOrNoTiming(child, interval)) {
                            childrenInInterval.push(child);
                        }
                    }
                    if (childrenInInterval.length === 0) {
                        continue; // No children to render
                    }

                    if (type === 'html') {
                        lineHeight = {};
                        linePadding = {};
                        fontSize = {};

                        /**
                         * Find the region defined for the cue.
                         */
                        // properties to be put in the "captionRegion" HTML element.
                        var cueRegionProperties = constructCueRegion(paragraph, div, cellUnit);

                        /**
                         * Find the style defined for the cue.
                         */
                        // properties to be put in the "paragraph" HTML element.
                        var cueStyleProperties = constructCueStyle(paragraph, cellUnit);

                        /**
                         * /!\ Create the cue HTML Element containing the whole cue.
                         */
                        var styleIDs = cueStyleProperties[1];
                        cueStyleProperties = cueStyleProperties[0];

                        // Final cue HTML element.
                        var cueParagraph = document.createElement('div');
                        cueParagraph.className = styleIDs;

                        // Create a wrapper containing the cue information about unicodeBidi and direction
                        // as they need to be defined on at this level.
                        // We append to the wrapper the cue itself.
                        var cueDirUniWrapper = constructCue(childrenInInterval, cellUnit);
                        cueDirUniWrapper.className = 'cueDirUniWrapper';

                        // If the style defines these two properties, we place them in cueContainer
                        // and delete them from the cue style so it is not added afterwards to the final cue.
                        if (arrayContains('unicode-bidi', cueStyleProperties)) {
                            cueDirUniWrapper.style.cssText += getPropertyFromArray('unicode-bidi', cueStyleProperties);
                            deletePropertyFromArray('unicode-bidi', cueStyleProperties);
                        }
                        if (arrayContains('direction', cueStyleProperties)) {
                            cueDirUniWrapper.style.cssText += getPropertyFromArray('direction', cueStyleProperties);
                            deletePropertyFromArray('direction', cueStyleProperties);
                        }

                        // Apply the linePadding property if it is specified in the cue style.
                        if (arrayContains('padding-left', cueStyleProperties) && arrayContains('padding-right', cueStyleProperties)) {
                            cueDirUniWrapper.innerHTML = applyLinePadding(cueDirUniWrapper, cueStyleProperties);
                        }

                        /**
                         * Clean and set the style and region for the cue to be returned.
                         */

                        // Remove the line padding property from being added at the "paragraph" element level.
                        if (arrayContains('padding-left', cueStyleProperties) && arrayContains('padding-right', cueStyleProperties)) {
                            deletePropertyFromArray('padding-left', cueStyleProperties);
                            deletePropertyFromArray('padding-right', cueStyleProperties);
                        }

                        // Remove the ID of the region from being added at the "paragraph" element level.
                        var regionID = '';
                        if (arrayContains('regionID', cueRegionProperties)) {
                            var wholeRegionID = getPropertyFromArray('regionID', cueRegionProperties);
                            regionID = wholeRegionID.slice(wholeRegionID.indexOf(':') + 1, wholeRegionID.length - 1);
                        }

                        // We link the p style to the finale cueParagraph element.
                        if (cueStyleProperties) {
                            cueParagraph.style.cssText = cueStyleProperties.join(' ') + 'display:flex;';
                        }
                        // We define the CSS style for the cue region.
                        if (cueRegionProperties) {
                            cueRegionProperties = cueRegionProperties.join(' ');
                        }

                        // We then place the cue wrapper inside the paragraph element.
                        cueParagraph.appendChild(cueDirUniWrapper);

                        // Final cue.
                        var finalCue = document.createElement('div');
                        finalCue.appendChild(cueParagraph);
                        finalCue.id = getCueID();
                        finalCue.style.cssText = 'position: absolute; margin: 0; display: flex; box-sizing: border-box; pointer-events: none;' + cueRegionProperties;

                        if (Object.keys(fontSize).length === 0) {
                            fontSize.defaultFontSize = '100';
                        }

                        // We add all the cue information in captionArray.
                        captionArray.push({
                            start: interval[0],
                            end: interval[1],
                            type: 'html',
                            cueHTMLElement: finalCue,
                            regions: regions,
                            regionID: regionID,
                            cueID: finalCue.id,
                            videoHeight: videoHeight,
                            videoWidth: videoWidth,
                            cellResolution: cellResolution,
                            fontSize: fontSize || {
                                defaultFontSize: '100'
                            },
                            lineHeight: lineHeight,
                            linePadding: linePadding
                        });

                    } else {
                        var text = '';
                        var textElements = childrenInInterval;
                        if (textElements.length) {
                            textElements.forEach(function (el) {
                                if (el.hasOwnProperty('span')) {
                                    var spanElements = el.span.__children;
                                    spanElements.forEach(function (spanEl) {
                                        // If metadata is present, do not process.
                                        if (spanElements.hasOwnProperty('metadata')) {
                                            return;
                                        }
                                        // If the element is a string
                                        if (spanEl.hasOwnProperty('#text')) {
                                            text += spanEl['#text'].replace(/[\r\n]+/gm, ' ').trim();
                                            // If the element is a 'br' tag
                                        } else if ('br' in spanEl) {
                                            // Create a br element.
                                            text += '\n';
                                        }
                                    });
                                } else if (el.hasOwnProperty('br')) {
                                    text += '\n';
                                } else {
                                    text += el['#text'].replace(/[\r\n]+/gm, ' ').trim();
                                }
                            });
                        }

                        captionArray.push({
                            start: interval[0],
                            end: interval[1],
                            data: text,
                            type: 'text'
                        });
                    }
                }
            }
        }

        if (errorMsg !== '') {
            log(errorMsg);
        }

        if (captionArray.length > 0) {
            return captionArray;
        } else { // This seems too strong given that there are segments with no TTML subtitles
            throw new Error(errorMsg);
        }
    }

    function setup() {
        /*
         * This TTML parser follows "EBU-TT-D SUBTITLING DISTRIBUTION FORMAT - tech3380" spec - https://tech.ebu.ch/docs/tech/tech3380.pdf.
         * */
        timingRegex = /^([0-9][0-9]+):([0-5][0-9]):([0-5][0-9])|(60)(\.([0-9])+)?$/; // Regex defining the time
        fontSize = {};
        lineHeight = {};
        linePadding = {};
        defaultLayoutProperties = {
            'top': 'auto;',
            'left': 'auto;',
            'width': '90%;',
            'height': '10%;',
            'align-items': 'flex-start;',
            'overflow': 'visible;',
            '-ms-writing-mode': 'lr-tb, horizontal-tb;',
            '-webkit-writing-mode': 'horizontal-tb;',
            '-moz-writing-mode': 'horizontal-tb;',
            'writing-mode': 'horizontal-tb;'
        };
        defaultStyleProperties = {
            'color': 'rgb(255,255,255);',
            'direction': 'ltr;',
            'font-family': 'monospace, sans-serif;',
            'font-style': 'normal;',
            'line-height': 'normal;',
            'font-weight': 'normal;',
            'text-align': 'start;',
            'justify-content': 'flex-start;',
            'text-decoration': 'none;',
            'unicode-bidi': 'normal;',
            'white-space': 'normal;',
            'width': '100%;'
        };
        fontFamilies = {
            monospace: 'font-family: monospace;',
            sansSerif: 'font-family: sans-serif;',
            serif: 'font-family: serif;',
            monospaceSansSerif: 'font-family: monospace, sans-serif;',
            monospaceSerif: 'font-family: monospace, serif;',
            proportionalSansSerif: 'font-family: Arial;',
            proportionalSerif: 'font-family: Times New Roman;',
            'default': 'font-family: monospace, sans-serif;'
        };
        textAlign = {
            right: ['justify-content: flex-end;', 'text-align: right;'],
            start: ['justify-content: flex-start;', 'text-align: start;'],
            center: ['justify-content: center;', 'text-align: center;'],
            end: ['justify-content: flex-end;', 'text-align: end;'],
            left: ['justify-content: flex-start;', 'text-align: left;']
        };
        multiRowAlign = {
            start: 'text-align: start;',
            center: 'text-align: center;',
            end: 'text-align: end;',
            auto: ''
        };
        wrapOption = {
            wrap: 'white-space: normal;',
            noWrap: 'white-space: nowrap;'
        };
        unicodeBidi = {
            normal: 'unicode-bidi: normal;',
            embed: 'unicode-bidi: embed;',
            bidiOverride: 'unicode-bidi: bidi-override;'
        };
        displayAlign = {
            before: 'align-items: flex-start;',
            center: 'align-items: center;',
            after: 'align-items: flex-end;'
        };
        writingMode = {
            lrtb: '-webkit-writing-mode: horizontal-tb;' +
                'writing-mode: horizontal-tb;',
            rltb: '-webkit-writing-mode: horizontal-tb;' +
                'writing-mode: horizontal-tb;' +
                'direction: rtl;' +
                'unicode-bidi: bidi-override;',
            tbrl: '-webkit-writing-mode: vertical-rl;' +
                'writing-mode: vertical-rl;' +
                '-webkit-text-orientation: upright;' +
                'text-orientation: upright;',
            tblr: '-webkit-writing-mode: vertical-lr;' +
                'writing-mode: vertical-lr;' +
                '-webkit-text-orientation: upright;' +
                'text-orientation: upright;',
            lr: '-webkit-writing-mode: horizontal-tb;' +
                'writing-mode: horizontal-tb;',
            rl: '-webkit-writing-mode: horizontal-tb;' +
                'writing-mode: horizontal-tb;' +
                'direction: rtl;',
            tb: '-webkit-writing-mode: vertical-rl;' +
                'writing-mode: vertical-rl;' +
                '-webkit-text-orientation: upright;' +
                'text-orientation: upright;'
        };
    }

    function parseTimings(timingStr) {
        // Test if the time provided by the caption is valid.
        var test = timingRegex.test(timingStr);
        var timeParts,
            parsedTime,
            frameRate;

        if (!test) {
            // Return NaN so it will throw an exception at internalParse if the time is incorrect.
            return NaN;
        }

        timeParts = timingStr.split(':');

        // Process the timings by decomposing it and converting it in numbers.
        parsedTime = (parseFloat(timeParts[0]) * SECONDS_IN_HOUR +
            parseFloat(timeParts[1]) * SECONDS_IN_MIN +
            parseFloat(timeParts[2]));

        // In case a frameRate is provided, we adjust the parsed time.
        if (timeParts[3]) {
            frameRate = ttml.tt.frameRate;
            if (frameRate && !isNaN(frameRate)) {
                parsedTime += parseFloat(timeParts[3]) / frameRate;
            } else {
                return NaN;
            }
        }
        return parsedTime;
    }

    function getNamespacePrefix(json, ns) {
        // Obtain the namespace prefix.
        var r = Object.keys(json)
            .filter(function (k) {
                return (k.split(':')[0] === 'xmlns' || k.split(':')[1] === 'xmlns') && json[k] === ns;
            }).map(function (k) {
                return k.split(':')[2] || k.split(':')[1];
            });
        if (r.length != 1) {
            return null;
        }
        return r[0];
    }

    function removeNamespacePrefix(json, nsPrefix) {
        for (var key in json) {
            if (json.hasOwnProperty(key)) {
                if ((typeof json[key] === 'object' || json[key] instanceof Object) && !Array.isArray(json[key])) {
                    removeNamespacePrefix(json[key], nsPrefix);
                } else if (Array.isArray(json[key])) {
                    for (var i = 0; i < json[key].length; i++) {
                        removeNamespacePrefix(json[key][i], nsPrefix);
                    }
                }
                var newKey = key.slice(key.indexOf(nsPrefix) + nsPrefix.length + 1);
                json[newKey] = json[key];
                delete json[key];
            }
        }
    }

    // backgroundColor = background-color, convert from camelCase to dash.
    function camelCaseToDash(key) {
        return key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
    }

    // Convert an RGBA value written in Hex to rgba(v,v,v,a).
    function convertHexToRGBA(rgba) {
        // Get the hexadecimal value without the #.
        var hex = rgba.slice(1);
        // Separate the values in pairs.
        var hexMatrice = hex.match(/.{2}/g);
        // Convert the alpha value in decimal between 0 and 1.
        var alpha = parseFloat(parseInt((parseInt(hexMatrice[3], 16) / 255) * 1000, 10) / 1000);
        // Get the standard RGB value.
        var rgb = hexMatrice.slice(0, 3).map(function (i) {
            return parseInt(i, 16);
        });
        // Return the RGBA value for CSS.
        return 'rgba(' + rgb.join(',') + ',' + alpha + ');';
    }

    // Return whether or not an array contains a certain text
    function arrayContains(text, array) {
        for (var i = 0; i < array.length; i++) {
            if (array[i].indexOf(text) > -1) {
                return true;
            }
        }
        return false;
    }

    // Return the whole value that contains "text"
    function getPropertyFromArray(text, array) {
        for (var i = 0; i < array.length; i++) {
            if (array[i].indexOf(text) > -1) {
                return array[i];
            }
        }
        return null;
    }

    // Delete a a property from an array.
    function deletePropertyFromArray(property, array) {
        array.splice(array.indexOf(getPropertyFromArray(property, array)), 1);
    }

    function mergeArrays(primeArray, arrayToAdd) {
        for (var i = 0; i < primeArray.length; i++) {
            for (var j = 0; j < arrayToAdd.length; j++) {
                // Take only the name of the property
                if (primeArray[i]) {
                    if (primeArray[i].split(':')[0].indexOf(arrayToAdd[j].split(':')[0]) > -1) {
                        primeArray.splice(i, 1);
                    }
                }
            }
        }
        return primeArray.concat(arrayToAdd);
    }

    /**
     * Processing of styling information:
     * - processStyle: return an array of strings with the cue style under a CSS style form.
     * - findStyleFromID: Return the unprocessed style from TTMLStyling corresponding to the ID researched.
     * - getProcessedStyle: Return the processed style(s) from the ID(s) received in entry.
     * **/

    // Compute the style properties to return an array with the cleaned properties.
    function processStyle(cueStyle, cellUnit, includeRegionStyles) {
        var properties = [];

        // Clean up from the xml2json parsing:
        for (var key in cueStyle) {
            if (cueStyle.hasOwnProperty(key)) {
                //Clean the properties from the parsing.
                var newKey = key.replace('ebutts:', '');
                newKey = newKey.replace('xml:', '');
                newKey = newKey.replace('tts:', '');

                // Clean the properties' names.
                newKey = camelCaseToDash(newKey);
                cueStyle[newKey] = cueStyle[key];
                delete cueStyle[key];
            }
        }

        // Line padding is computed from the cellResolution.
        if ('line-padding' in cueStyle) {
            var valuePadding = parseFloat(cueStyle['line-padding'].slice(cueStyle['line-padding'].indexOf(':') + 1,
                cueStyle['line-padding'].indexOf('c')));
            if ('id' in cueStyle) {
                linePadding[cueStyle.id] = valuePadding;
            }
            var valuePaddingInPx = valuePadding * cellUnit[0] + 'px;';
            properties.push('padding-left:' + valuePaddingInPx);
            properties.push('padding-right:' + valuePaddingInPx);
        }
        // Font size is computed from the cellResolution.
        if ('font-size' in cueStyle) {
            var valueFtSize = parseFloat(cueStyle['font-size'].slice(cueStyle['font-size'].indexOf(':') + 1,
                cueStyle['font-size'].indexOf('%')));
            if ('id' in cueStyle) {
                fontSize[cueStyle.id] = valueFtSize;
            }
            var valueFtSizeInPx = valueFtSize / 100 * cellUnit[1] + 'px;';
            properties.push('font-size:' + valueFtSizeInPx);
        }
        // Line height is computed from the cellResolution.
        if ('line-height' in cueStyle) {
            if (cueStyle['line-height'] === 'normal') {
                properties.push('line-height: normal;');
            } else {
                var valueLHSize = parseFloat(cueStyle['line-height'].slice(cueStyle['line-height'].indexOf(':') + 1,
                    cueStyle['line-height'].indexOf('%')));
                if ('id' in cueStyle) {
                    lineHeight[cueStyle.id] = valueLHSize;
                }
                var valueLHSizeInPx = valueLHSize / 100 * cellUnit[1] + 'px;';
                properties.push('line-height' + ':' + valueLHSizeInPx);
            }
        }
        // Font-family can be specified by a generic family name or a custom family name.
        if ('font-family' in cueStyle) {
            if (cueStyle['font-family'] in fontFamilies) {
                properties.push(fontFamilies[cueStyle['font-family']]);
            } else {
                properties.push('font-family:' + cueStyle['font-family'] + ';');
            }
        }
        // Text align needs to be set from two properties:
        // The standard text-align CSS property.
        // The justify-content property as we use flex boxes.
        if ('text-align' in cueStyle) {
            if (cueStyle['text-align'] in textAlign) {
                properties.push(textAlign[cueStyle['text-align']][0]);
                properties.push(textAlign[cueStyle['text-align']][1]);
            }
        }
        // Multi Row align is set only by the text-align property.
        // TODO: TO CHECK
        if ('multi-row-align' in cueStyle) {
            if (arrayContains('text-align', properties) && cueStyle['multi-row-align'] != 'auto') {
                deletePropertyFromArray('text-align', properties);
            }
            if (cueStyle['multi-row-align'] in multiRowAlign) {
                properties.push(multiRowAlign[cueStyle['multi-row-align']]);
            }
        }
        // Background color can be specified from hexadecimal (RGB or RGBA) value.
        var rgbaValue;
        if ('background-color' in cueStyle) {
            if (cueStyle['background-color'].indexOf('#') > -1 && (cueStyle['background-color'].length - 1) === 8) {
                rgbaValue = convertHexToRGBA(cueStyle['background-color']);
                properties.push('background-color: ' + rgbaValue);
            } else {
                properties.push('background-color:' + cueStyle['background-color'] + ';');
            }
        }
        // Color can be specified from hexadecimal (RGB or RGBA) value.
        if ('color' in cueStyle) {
            if (cueStyle.color.indexOf('#') > -1 && (cueStyle.color.length - 1) === 8) {
                rgbaValue = convertHexToRGBA(cueStyle.color);
                properties.push('color: ' + rgbaValue);
            } else {
                properties.push('color:' + cueStyle.color + ';');
            }
        }
        // Wrap option is determined by the white-space CSS property.
        if ('wrap-option' in cueStyle) {
            if (cueStyle['wrap-option'] in wrapOption) {
                properties.push(wrapOption[cueStyle['wrap-option']]);
            } else {
                properties.push('white-space:' + cueStyle['wrap-option']);
            }
        }
        // Unicode bidi is determined by the unicode-bidi CSS property.
        if ('unicode-bidi' in cueStyle) {
            if (cueStyle['unicode-bidi'] in unicodeBidi) {
                properties.push(unicodeBidi[cueStyle['unicode-bidi']]);
            } else {
                properties.push('unicode-bidi:' + cueStyle['unicode-bidi']);
            }
        }

        // Standard properties identical to CSS.

        if ('font-style' in cueStyle) {
            properties.push('font-style:' + cueStyle['font-style'] + ';');
        }
        if ('font-weight' in cueStyle) {
            properties.push('font-weight:' + cueStyle['font-weight'] + ';');
        }
        if ('direction' in cueStyle) {
            properties.push('direction:' + cueStyle.direction + ';');
        }
        if ('text-decoration' in cueStyle) {
            properties.push('text-decoration:' + cueStyle['text-decoration'] + ';');
        }

        if (includeRegionStyles) {
            properties = properties.concat(processRegion(cueStyle, cellUnit));
        }

        // Handle white-space preserve
        if (ttml.tt.hasOwnProperty('xml:space')) {
            if (ttml.tt['xml:space'] === 'preserve') {
                properties.push('white-space: pre;');
            }
        }

        return properties;
    }

    // Find the style set by comparing the style IDs available.
    // Return null if no style is found
    function findStyleFromID(ttmlStyling, cueStyleID) {
        // For every styles available, search the corresponding style in ttmlStyling.
        for (var j = 0; j < ttmlStyling.length; j++) {
            var currStyle = ttmlStyling[j];
            if (currStyle['xml:id'] === cueStyleID || currStyle.id === cueStyleID) {
                // Return the style corresponding to the ID in parameter.
                return currStyle;
            }
        }
        return null;
    }
    // Return the computed style from a certain ID.
    function getProcessedStyle(reference, cellUnit, includeRegionStyles) {
        var styles = [];
        var ids = reference.match(/\S+/g);
        ids.forEach(function (id) {
            // Find the style for each id received.
            var cueStyle = findStyleFromID(ttmlStyling, id);
            if (cueStyle) {
                // Process the style for the cue in CSS form.
                // Send a copy of the style object, so it does not modify the original by cleaning it.
                var stylesFromId = processStyle(JSON.parse(JSON.stringify(cueStyle)), cellUnit, includeRegionStyles);
                styles = styles.concat(stylesFromId);
            }
        });
        return styles;
    }

    // Calculate relative left, top, width, height from extent and origin in percent.
    // Return object with {left, top, width, height} as numbers in percent or null.
    function getRelativePositioning(element, ttExtent) {

        let pairRe = /([\d\.]+)(%|px)\s+([\d\.]+)(%|px)/;

        if (('tts:extent' in element) && ('tts:origin' in element) ) {
            let extentParts = pairRe.exec(element['tts:extent']);
            let originParts = pairRe.exec(element['tts:origin']);
            if (extentParts === null || originParts === null) {
                log('Bad extent or origin: ' + element['tts:extent'] + ' ' + element['tts:origin']);
                return null;
            }
            let width = parseFloat(extentParts[1]);
            let height = parseFloat(extentParts[3]);
            let left = parseFloat(originParts[1]);
            let top = parseFloat(originParts[3]);

            if (ttExtent) { // Should give overall scale in pixels
                let ttExtentParts = pairRe.exec(ttExtent);
                if (ttExtentParts === null || ttExtentParts[2] !== 'px' || ttExtentParts[4] !== 'px') {
                    log('Bad tt.extent: ' + ttExtent);
                    return null;
                }
                let exWidth = parseFloat(ttExtentParts[1]);
                let exHeight = parseFloat(ttExtentParts[3]);
                if (extentParts[2] === 'px') {
                    width = width / exWidth * 100;
                }
                if (extentParts[4] === 'px') {
                    height = height / exHeight * 100;
                }
                if (originParts[2] === 'px') {
                    left = left / exWidth * 100;
                }
                if (originParts[4] === 'px') {
                    top = top / exHeight * 100;
                }
            }
            return { 'left': left, 'top': top, 'width': width, 'height': height };
        } else {
            return null;
        }
    }

    /**
     * Processing of layout information:
     * - processRegion: return an array of strings with the cue region under a CSS style form.
     * - findRegionFromID: Return the unprocessed region from TTMLLayout corresponding to the ID researched.
     * - getProcessedRegion: Return the processed region(s) from the ID(s) received in entry.
     ***/

    // Compute the region properties to return an array with the cleaned properties.
    function processRegion(cueRegion, cellUnit) {
        var properties = [];

        // Clean up from the xml2json parsing:
        for (var key in cueRegion) {
            //Clean the properties from the parsing.
            var newKey = key.replace('tts:', '');
            newKey = newKey.replace('xml:', '');

            // Clean the properties' names.
            newKey = camelCaseToDash(newKey);
            cueRegion[newKey] = cueRegion[key];
            if (newKey !== key) {
                delete cueRegion[key];
            }
        }
        // Extent property corresponds to width and height
        if ('extent' in cueRegion) {
            var coordsExtent = cueRegion.extent.split(/\s/);
            properties.push('width: ' + coordsExtent[0] + ';');
            properties.push('height: ' + coordsExtent[1] + ';');
        }
        // Origin property corresponds to top and left
        if ('origin' in cueRegion) {
            var coordsOrigin = cueRegion.origin.split(/\s/);
            properties.push('left: ' + coordsOrigin[0] + ';');
            properties.push('top: ' + coordsOrigin[1] + ';');
        }
        // DisplayAlign property corresponds to vertical-align
        if ('display-align' in cueRegion) {
            properties.push(displayAlign[cueRegion['display-align']]);
        }
        // WritingMode is not yet implemented (for CSS3, to come)
        if ('writing-mode' in cueRegion) {
            properties.push(writingMode[cueRegion['writing-mode']]);
        }
        // Style will give to the region the style properties from the style selected
        if ('style' in cueRegion) {
            var styleFromID = getProcessedStyle(cueRegion.style, cellUnit, true);
            properties = properties.concat(styleFromID);
        }

        // Standard properties identical to CSS.

        if ('padding' in cueRegion) {
            properties.push('padding:' + cueRegion.padding + ';');
        }
        if ('overflow' in cueRegion) {
            properties.push('overflow:' + cueRegion.overflow + ';');
        }
        if ('show-background' in cueRegion) {
            properties.push('show-background:' + cueRegion['show-background'] + ';');
        }
        if ('id' in cueRegion) {
            properties.push('regionID:' + cueRegion.id + ';');
        }

        return properties;
    }

    // Find the region set by comparing the region IDs available.
    // Return null if no region is found
    function findRegionFromID(ttmlLayout, cueRegionID) {
        // For every region available, search the corresponding style in ttmlLayout.
        for (var j = 0; j < ttmlLayout.length; j++) {
            var currReg = ttmlLayout[j];
            if (currReg['xml:id'] === cueRegionID || currReg.id === cueRegionID) {
                // Return the region corresponding to the ID in parameter.
                return currReg;
            }
        }
        return null;
    }

    // Return the computed region from a certain ID.
    function getProcessedRegion(reference, cellUnit) {
        var regions = [];
        var ids = reference.match(/\S+/g);
        ids.forEach(function (id) {
            // Find the region for each id received.
            var cueRegion = findRegionFromID(ttmlLayout, id);
            if (cueRegion) {
                // Process the region for the cue in CSS form.
                // Send a copy of the style object, so it does not modify the original by cleaning it.
                var regionsFromId = processRegion(JSON.parse(JSON.stringify(cueRegion)), cellUnit);
                regions = regions.concat(regionsFromId);
            }
        });
        return regions;
    }

    //Return the cellResolution defined by the TTML document.
    function getCellResolution() {
        var defaultCellResolution = [32, 15]; // Default cellResolution.
        if (ttml.tt.hasOwnProperty('ttp:cellResolution')) {
            return ttml.tt['ttp:cellResolution'].split(' ').map(parseFloat);
        } else {
            return defaultCellResolution;
        }
    }

    // Return the cue wrapped into a span specifying its linePadding.
    function applyLinePadding(cueHTML, cueStyle) {
        // Extract the linePadding property from cueStyleProperties.
        var linePaddingLeft = getPropertyFromArray('padding-left', cueStyle);
        var linePaddingRight = getPropertyFromArray('padding-right', cueStyle);
        var linePadding = linePaddingLeft.concat(' ' + linePaddingRight + ' ');

        // Declaration of the HTML elements to be used in the cue innerHTML construction.
        var outerHTMLBeforeBr = '';
        var outerHTMLAfterBr = '';
        var cueInnerHTML = '';

        // List all the nodes of the subtitle.
        var nodeList = Array.prototype.slice.call(cueHTML.children);
        // Take a br element as reference.
        var brElement = cueHTML.getElementsByClassName('lineBreak')[0];
        // First index of the first br element.
        var idx = nodeList.indexOf(brElement);
        // array of all the br element indices
        var indices = [];
        // Find all the indices of the br elements.
        while (idx != -1) {
            indices.push(idx);
            idx = nodeList.indexOf(brElement, idx + 1);
        }

        // Strings for the cue innerHTML construction.
        var spanStringEnd = '<\/span>';
        var br = '<br>';
        var clonePropertyString = '<span' + ' class="spanPadding" ' + 'style="-webkit-box-decoration-break: clone; box-decoration-break: clone; ';

        // If br elements are found:
        if (indices.length) {
            // For each index of a br element we compute the HTML coming before and/or after it.
            indices.forEach(function (i, index) {
                // If this is the first line break, we compute the HTML of the element coming before.
                if (index === 0) {
                    var styleBefore = '';
                    // for each element coming before the line break, we add its HTML.
                    for (var j = 0; j < i; j++) {
                        outerHTMLBeforeBr += nodeList[j].outerHTML;
                        // If this is the first element, we add its style to the wrapper.
                        if (j === 0) {
                            styleBefore = linePadding.concat(nodeList[j].style.cssText);
                        }
                    }
                    // The before element will comprises the clone property (for line wrapping), the style that
                    // need to be applied (ex: background-color) and the rest og the HTML.
                    outerHTMLBeforeBr = clonePropertyString + styleBefore + '">' + outerHTMLBeforeBr;
                }
                // For every element of the list, we compute the element coming after the line break.s
                var styleAfter = '';
                // for each element coming after the line break, we add its HTML.
                for (var k = i + 1; k < nodeList.length; k++) {
                    outerHTMLAfterBr += nodeList[k].outerHTML;
                    // If this is the last element, we add its style to the wrapper.
                    if (k === nodeList.length - 1) {
                        styleAfter += linePadding.concat(nodeList[k].style.cssText);
                    }
                }

                // The before element will comprises the clone property (for line wrapping), the style that
                // need to be applied (ex: background-color) and the rest og the HTML.
                outerHTMLAfterBr = clonePropertyString + styleAfter + '">' + outerHTMLAfterBr;

                // For each line break we must add the before and/or after element to the final cue as well as
                // the line break when needed.
                if (outerHTMLBeforeBr && outerHTMLAfterBr && index === (indices.length - 1)) {
                    cueInnerHTML += outerHTMLBeforeBr + spanStringEnd + br + outerHTMLAfterBr + spanStringEnd;
                } else if (outerHTMLBeforeBr && outerHTMLAfterBr && index !== (indices.length - 1)) {
                    cueInnerHTML += outerHTMLBeforeBr + spanStringEnd + br + outerHTMLAfterBr + spanStringEnd + br;
                } else if (outerHTMLBeforeBr && !outerHTMLAfterBr) {
                    cueInnerHTML += outerHTMLBeforeBr + spanStringEnd;
                } else if (!outerHTMLBeforeBr && outerHTMLAfterBr && index === (indices.length - 1)) {
                    cueInnerHTML += outerHTMLAfterBr + spanStringEnd;
                } else if (!outerHTMLBeforeBr && outerHTMLAfterBr && index !== (indices.length - 1)) {
                    cueInnerHTML += outerHTMLAfterBr + spanStringEnd + br;
                }
            });
        } else {
            // If there is no line break in the subtitle, we simply wrap cue in a span indicating the linePadding.
            var style = '';
            for (var k = 0; k < nodeList.length; k++) {
                style += nodeList[k].style.cssText;
            }
            cueInnerHTML = clonePropertyString + linePadding + style + '">' + cueHTML.innerHTML + spanStringEnd;
        }
        return cueInnerHTML;
    }

    /*
    * Create the cue element
     * I. The cues are text only:
     *      i) The cue contains a 'br' element
     *      ii) The cue contains a span element
     *      iii) The cue contains text
     */

    function constructCue(cueElements, cellUnit) {
        var cue = document.createElement('div');
        cueElements.forEach(function (el) {
            // If metadata is present, do not process.
            if (el.hasOwnProperty('metadata')) {
                return;
            }

            /**
             * If the p element contains spans: create the span elements.
             */
            if (el.hasOwnProperty('span')) {

                // Stock the span subtitles in an array (in case there are only one value).
                var spanElements = el.span.__children;

                // Create the span element.
                var spanHTMLElement = document.createElement('span');
                // Extract the style of the span.
                if (el.span.hasOwnProperty('style')) {
                    var spanStyle = getProcessedStyle(el.span.style, cellUnit);
                    spanHTMLElement.className = 'spanPadding ' + el.span.style;
                    spanHTMLElement.style.cssText = spanStyle.join(' ');
                }

                // if the span has more than one element, we check for each of them their nature (br or text).
                spanElements.forEach(function (spanEl) {
                    // If metadata is present, do not process.
                    if (spanElements.hasOwnProperty('metadata')) {
                        return;
                    }
                    // If the element is a string
                    if (spanEl.hasOwnProperty('#text')) {
                        var textNode = document.createTextNode(spanEl['#text']);
                        spanHTMLElement.appendChild(textNode);
                        // If the element is a 'br' tag
                    } else if ('br' in spanEl) {
                        // To handle br inside span we need to add the current span
                        // to the cue and then create a br and add that the cue
                        // then create a new span that we use for the next line of
                        // text, that is a copy of the current span

                        // Add the current span to the cue, only if it has childNodes (text)
                        if (spanHTMLElement.hasChildNodes()) {
                            cue.appendChild(spanHTMLElement);
                        }

                        // Create a br and add that to the cue
                        var brEl = document.createElement('br');
                        brEl.className = 'lineBreak';
                        cue.appendChild(brEl);

                        // Create an replacement span and copy the style and classname from the old one
                        var newSpanHTMLElement = document.createElement('span');
                        newSpanHTMLElement.className = spanHTMLElement.className;
                        newSpanHTMLElement.style.cssText = spanHTMLElement.style.cssText;

                        // Replace the current span with the one we just created
                        spanHTMLElement = newSpanHTMLElement;
                    }
                });
                // We append the element to the cue container.
                cue.appendChild(spanHTMLElement);
            }

            /**
             * Create a br element if there is one in the cue.
             */
            else if (el.hasOwnProperty('br')) {
                // We append the line break to the cue container.
                var brEl = document.createElement('br');
                brEl.className = 'lineBreak';
                cue.appendChild(brEl);
            }

            /**
             * Add the text that is not in any inline element
             */
            else if (el.hasOwnProperty('#text')) {
                // Add the text to an individual span element (to add line padding if it is defined).
                var textNode = document.createElement('span');
                textNode.textContent = el['#text'];

                // We append the element to the cue container.
                cue.appendChild(textNode);
            }
        });
        return cue;
    }

    function constructCueRegion(cue, div, cellUnit) {
        var cueRegionProperties = []; // properties to be put in the "captionRegion" HTML element
        // Obtain the region ID(s) assigned to the cue.
        var pRegionID = cue.region;
        // If div has a region.
        var divRegionID = div.region;

        var divRegion;
        var pRegion;

        // If the div element reference a region.
        if (divRegionID) {
            divRegion = getProcessedRegion(divRegionID, cellUnit);
        }
        // If the p element reference a region.
        if (pRegionID) {
            pRegion = cueRegionProperties.concat(getProcessedRegion(pRegionID, cellUnit));
            if (divRegion) {
                cueRegionProperties = mergeArrays(divRegion, pRegion);
            } else {
                cueRegionProperties = pRegion;
            }
        } else if (divRegion) {
            cueRegionProperties = divRegion;
        }

        // Add initial/default values to what's not defined in the layout:
        applyDefaultProperties(cueRegionProperties, defaultLayoutProperties);

        return cueRegionProperties;
    }

    function constructCueStyle(cue, cellUnit) {
        var cueStyleProperties = []; // properties to be put in the "paragraph" HTML element
        // Obtain the style ID(s) assigned to the cue.
        var pStyleID = cue.style;
        // If body has a style.
        var bodyStyleID = ttml.tt.body.style;
        // If div has a style.
        var divStyleID = ttml.tt.body.div.style;

        var bodyStyle;
        var divStyle;
        var pStyle;
        var styleIDs = '';

        // If the body element reference a style.
        if (bodyStyleID) {
            bodyStyle = getProcessedStyle(bodyStyleID, cellUnit);
            styleIDs = 'paragraph ' + bodyStyleID;
        }

        // If the div element reference a style.
        if (divStyleID) {
            divStyle = getProcessedStyle(divStyleID, cellUnit);
            if (bodyStyle) {
                divStyle = mergeArrays(bodyStyle, divStyle);
                styleIDs += ' ' + divStyleID;
            } else {
                styleIDs = 'paragraph ' + divStyleID;
            }
        }

        // If the p element reference a style.
        if (pStyleID) {
            pStyle = getProcessedStyle(pStyleID, cellUnit);
            if (bodyStyle && divStyle) {
                cueStyleProperties = mergeArrays(divStyle, pStyle);
                styleIDs += ' ' + pStyleID;
            } else if (bodyStyle) {
                cueStyleProperties = mergeArrays(bodyStyle, pStyle);
                styleIDs += ' ' + pStyleID;
            } else if (divStyle) {
                cueStyleProperties = mergeArrays(divStyle, pStyle);
                styleIDs += ' ' + pStyleID;
            } else {
                cueStyleProperties = pStyle;
                styleIDs = 'paragraph ' + pStyleID;
            }
        } else if (bodyStyle && !divStyle) {
            cueStyleProperties = bodyStyle;
        } else if (!bodyStyle && divStyle) {
            cueStyleProperties = divStyle;
        }

        // Add initial/default values to what's not defined in the styling:
        applyDefaultProperties(cueStyleProperties, defaultStyleProperties);

        return [cueStyleProperties, styleIDs];
    }

    function applyDefaultProperties(array, defaultProperties) {
        for (var key in defaultProperties) {
            if (defaultProperties.hasOwnProperty(key)) {
                if (!arrayContains(key, array)) {
                    array.push(key + ':' + defaultProperties[key]);
                }
            }
        }
    }

    instance = {
        parse: parse,
        setConfig: setConfig
    };

    setup();
    return instance;
}
TTMLParser.__dashjs_factory_name = 'TTMLParser';
export
default FactoryMaker.getSingletonFactory(TTMLParser);


text:
Epitonium muricatum is een slakkensoort uit de familie van de Epitoniidae. De wetenschappelijke naam van de soort is voor het eerst geldig gepubliceerd in 1826 door Risso.

Epitoniidae

redpajama_set_name: RedPajamaWikipedia


Along with a thick mulch layer, we used a couple foliar sprays a week with @mountainorganicsbotanicals tonics for supplementation and pest management.
A compost wash or tea was applied as needed and the Team couldn't be happier with season 7 in these two 30 gallon, fourth cycle, no till pots.
Season 8 update...Two 30 gallon, fourth cycle, no till pots on day 31 of bloom.
The back pot, we swear there is another 30 gallon pot back there, hosts one female plant named Queen Anne's Revenge and is a cross between Bloodwreck and Space Queen bred by @subcool420.
The mulch layer consists of leaf and stem prunings which feeds the soil.
#weedculture #cannabisculture #porrazo #high #seeds #kush #stoned #weedo #memeweed #blunt #weedstagram #hierbabomba #buenosdias #marihuanalegal #argentina #tuja #buenoshumos #maryjane #smokeweed #indica #weedlove #highsociety #espa #maria #chusta #cannabiscomunity #weedspain #weednation #rawlife #tbt .
The Happy Crew is hanging out @thegallery_fife today! And we got you 😂😂 Happy 4/20 eve!
Sign up to be a member prior for free admission.
Por acá todo muy chill !!
ramada kuftan available in size S-M 2 pieces.
boy friend or straight! chose your favorite .


text:
Q: How to change the vertical alignment line in matlab code editor? I want to change the vertical alignment line in matlab code editor in order to have a better illustration when I publish my .m file as html one! how can I do that? I searched but came up with this solution that I use multiple line code writing using "..." notation in my code!
I should write this way:
str = "This sentence is " ...
           "very large one";

So I don't want to do that. How can I change its default value.
see the picture below!

thanks in advance :)

A: In the main window under preferences\Editor\Display you'll find "Right-hand text limit", where you can specify the number of columns between every vertical alignment line.
It's limited to 160 columns, unfortunately.
(ver. Matlab 2013a)
under preferences\Editor\Language you can also find a checkbox "Wrap comments automatically" and some other options just concerning comments. Sometimes the wrapping there also gets annoying.

Edit: the 160 columns would exactly fill my screen. So maybe you can choose a bigger value, if you have a bigger resolution/screen.

redpajama_set_name: RedPajamaStackExchange


Evaluating Unconventional Monetary Policies Why Aren't They More Effective?
We use a general equilibrium finance model that features explicit government purchases of private debts to shed light on some of the principal working mechanisms of the Federal Reserve's large-scale asset purchases (LSAP) and their macroeconomic effects. Our model predicts that unless private asset purchases are highly persistent and extremely large (on the order of more than 50% of annual GDP), money injections through LSAP cannot effectively boost aggregate output and employment even if inflation is fully anchored and the real interest rate significantly reduced. Our framework also sheds light on some long- standing financial puzzles and monetary policy questions facing central banks around the world, such as (i) the flight to liquidity under a credit crunch and debt crisis, (ii) the liquidity trap, and (iii) the low inflation puzzle under quantitative easing.


South did have 7 spades in her hand QJ10xxxx.
Director was called and allowed bidding to continue.
Clearly the comment provides UI, but in order to rule it would be necessary to poll players with the North hand and see what they would do over 4H in the absence of UI. Even if they Pass, the TD should consider whether South might have now bid 4S. Somebody should tell South that she could have corrected her 1NT bid if she had said something before her partner called, but having failed to do that she shouldn't say anything at all.
I think there is very little UI here, the subsequent spade bidding says he has 6 or 7 spades, the only info it gives is that he might have more (or less) values than 1N would indicate.
Gordon is of course right but I doubt there would be any adjustment.
In addition, the player should be educated that they are not required to tell anyone when they've misbid, and should especially not do this during the auction or while they're defending. The only time you can say anything is if you realize you've made an unintended call during the short period when correcting it is allowed. And if you're not sure what that period is, you should call the TD without stating the reason, so you can find out your rights before giving too much UI (there will be some UI from the fact that you needed to call, but partner will have to guess what it means).
Seems to me this is a good educational opportunity, and probably no more than that, although I do wonder... is "I have very little UI" akin to "I'm only a little bit pregnant"?
Not exactly, you can clearly have UI, but it can have no effect in that there is nothing suggested by it.


Model: Dinan Supercharged; Dinan throttle body, valve cover, strut bar, etc.
Dinan claims 345 Horsepower to the crank.
-e36 diff cover, dual ear w/ poly bushings.
-Hood and front bumper stripped and re-painted in fall 2013 by M Performance. A few scratches and nicks apparent from moderate use but paint overall in good shape.
Three owners, I'm the third owner. Car has been pampered. Previous owners had most maintenance performed by TMJ Bimmers in Houston; subframe and alignment done at M Performance in Spring, TX.
Car is garaged in climate controlled environment, and protected from the elements.
* Service up to date (2016) including new KN Air filter, oil change, etc.
~ The car is mechanically very solid and sounds great.
~ The convertible top is in great shape - it's not currently connected to power and is manually put up/down. The hardware for the power top is still in place and functional (to my knowledge).
~ I can walk through any issues with a potential buyer. Carfax available upon request, as are more pictures.
I recognize the description of this coupe from Texas abotu 18 months ago. No photos or mileage listed but it had 98k miels at the time. It's full of good upgrades. The new price is optimistic for the mileage though.


text:
Two of Virginia's Pearl Harbor veterans are now identified
Dave Ress
• Daily Press • December 7, 2021
Rodger C. Butts (Defense POW/MIA Accounting Agency)
(Tribune News Service) — The remains of two Portsmouth, Va., sailors who died during the Japanese attack on Pearl Harbor have been definitively identified.
Navy Petty Officers 1st Class Octavius Mabine, 21, and Rodger C. Butts, 47, were on the battleship USS Oklahoma when Japanese torpedo-bombers attacked the warship while it was moored at Pearl Harbor's "Battleship Row," on Ford Island. The Oklahoma was alongside the USS Maryland and farthest out from the shore, making it one of the first ships attacked.
Their remains were among those identified by a 6-year-old effort of the Defense/POW Accounting Agency that ends today, the 80th anniversary of the Pearl Harbor attack.
Just before 8 a.m. on Dec. 7, 1941, three torpedoes struck the Oklahoma's hull below the waterline in the space of about 10 minutes, destroying the steel bulge meant to protect the ship from torpedo attack, and rupturing fuel tanks.
Sailors racing to the warship's anti-aircraft guns were unable to fire them because a key piece was still in the ship's armory.
As the Oklahoma began to capsize, it was hit by two more torpedoes and within 12 minutes had rolled over, leaving only part of its keel and starboard side above the water.
While some sailors were able to escape, either by climbing the lines connecting the Oklahoma with the Maryland or by swimming through the oily water around their ship, 429 of the ship's company were killed or missing.
The Defense POW/MIA Accounting Agency identified Mabine's and Butts' remains from among those of 388 long-unidentified Oklahoma sailors buried at the National Memorial Cemetery of the Pacific — the "Punchbowl" — in Honolulu.
Labs in Nebraska and Hawaii have identified 355.
The accounting agency exhumed those remains in 2015 and, in addition to conducting anthropological and dental records analyses, called on scientists from the Armed Forces Medical Examiner System to conduct mitochondrial DNA and Y chromosome DNA analyses to identify the fallen.
Mabine's and Butts' names are recorded on the Walls of the Missing at the Punchbowl, along with the others who are missing from World War II. A rosette will be placed next to their names to indicate that they have been accounted for.
The remains of the 33 who could not be identified individually will be reburied today in Honolulu's National Memorial Cemetery of the Pacific.
dress@dailypress.com
©2021 Daily Press.
Visit dailypress.com.
80th anniversary of Pearl Harbor brings end to victim-identification program

redpajama_set_name: RedPajamaCommonCrawl


text:
Canada in Burma: Fred Kagawa
In 1996, the Canadian National Defence Recovery Team traveled deep into the jungle of Myanmar (formerly known as Burma) to recover the bodies of six Canadian airmen killed during the Second World War. The trip reminds us that there were many Canadians stationed in places other than Europe and Africa during the fighting.
An estimated 8,000 Canadians served in Burma during the Second World War; five hundred lost their lives battling Japanese imperialism. Most of these men served with the Royal Air Force (RAF).
The RAF was primarily responsible for supplying the Allied ground troops with supplies in Burma. Myanmar's mountainous, jungle terrain made ground transport a logistical nightmare and forced the troops to rely on regular airdrops. However, it also meant that Canadian pilots were forced to fly in heavy rain and low cloud coverage during Burma's five-month-long monsoon season, conditions that would ordinarily leave a plane grounded. It was one of those flights that led to the engagement of the 1995 Recovery Team mentioned earlier. Many Canadian pilots were also tasked with defending military bases from Japanese attacks and often engaged in fierce dogfights during major Allied offensives.
One Canadian who served on the ground was Fred Kagawa. After being rejected by the RCAF due to his Japanese heritage, Kagawa was later recruited and trained as an interpreter by the Canadian Intelligence Corps. In Burma, he was assigned to the Psychological Warfare Broadcasting Unit in Rangoon where he spent his days translating Allied propaganda into Japanese to undermine enemy morale. On August 14, 1945 Kagawa was finally able to announce that Japan had surrendered and that the three-year-long Burma Campaign was over.
Fred Kagawa, Canadian Intelligence Corps, Vancouver Tech,. c.1942-43 (Credit: The Estate of Doris Shadbolt/ via University of British Columbia)
To learn more about Fred Kagawa, please read this digital issue from the Asian Diaspora Research Group.
For more on the Canadian National Defence Recovery Team and their 1995 mission, see Canada's National Film Board documentary, "Lost Over Burma: Search for Closure".
This Global News creation: "Discovery of Second World War plane in Burmese jungle brings closure to Peterborough family", tells of a recent development in the story.
Main photo: F.H. Sproule and Warrant Officer H.E. Johnny Walker. Two Canadian Hurri-bombers who were among the busiest men on the Burma front. 28 February 1945 (Credit: LAC M# 4283438).
Our Intention is to educate Canadian Citizens so that they:
Appreciate the role of our military heritage in protecting Canadian interests, values and beliefs.
Understand the role our military history has had in shaping our country and the world.
Are inspired to be engaged and well-informed participatory citizens of Canada.
join us and
Become a member! Join a community of like-minded individuals, gain access to exclusive Valour Canada content and events, and help us connect Canadian youth to our shared military heritage.
Please sign up to receive Valour Canada programming and event updates.
VALOUR CANADA will use the information you provide on this form to be in touch with you and to provide updates and marketing.


text:
Data science: A new pillar to add to the traditional sciences
Sean Owen
The last decade has seen bigger and faster developments in the technology space than the world experienced in the past century, and this is permeating right the way through to the education programmes and approaches that are shaping our business leaders, doctors and scientists of tomorrow.
In terms of the technology space, big data solutions are quickly becoming one of the most important overall areas. As such, the science behind this relatively new field is gathering pace rapidly, so there has never been a better time to pursue a career in data science career, and the latent data insights have never been so potentially valuable.
Much of the current enthusiasm for data science focuses on technologies that simplify the data interpretation process and the related open-source tools applicable for cloud computing, and visualisation environments. While these are all important breakthroughs, the people with the skill and mindset to put them to good use are by far and away the most valuable asset.
Data science has one foot squarely in the world of statistics and linear algebra, which are the sorts of applied mathematical skills, but in practicality it is a several steps down the evolutionary line.
While applied maths and statistics have been taught in schools for a long time now, the increasing size of the data and the complexity of tools required by statisticians and critical thinkers will require them to learn skills to deal with these multifaceted data systems, and gain the knowledge of complex software practices too.
The data scientist will be a crucial element for many companies across all manner of verticals in years to come, key to performing mission critical functions such as; running A/B" testing of platforms for apps or websites; analysing A/B" tests with specific business or product objectives in mind; building recommendation engines and tuning their algorithms; building fraud detection systems; predict customer churn rates for subscription based industries like Mobile Network Operators; and even running historical statistical analysis on customer shopping behaviour.
Read more on STEM:
Awareness is key for unlocking the futures of British students and businesses
Nurturing STEM education can take British firms into the future, says IBM's UK chief exec
Two birds, one stone: Facing up to the gender imbalance and skills shortage in STEM
As companies increasingly look to find new value from their existing assets and differentiate themselves in crowded and competitive markets, the place of the data scientist to business strategy and objectives is becoming pivotal.
And as demand outstrips supply, a shortage of data science exponents is becoming a serious constraint in many different sectors.
In just over a decade we have transitioned from a relatively data-scarce world, to a data-rich world, where the amount of data available is already virtually limitless and doubling almost every other year. The call to action is clear enough: we need data scientists now, just like we continue to need physicists, chemists and biologists.
There is good news however. August saw a record high, with the number of students taking STEM A-levels increasing by more than 38,000 since 2010. Similarly, computer sciences applications at university were up a staggering 13 per cent, to 97,110 the greatest percentage increase of any of the other top ten most studied subjects.
This is good news for British businesses looking to build todays workforces with a view to the business demands of the future, and more data scientists will clearly come from this increasing pool of talent.
The advance of big data shows no signs of slowing down, and schools, colleges and universities are beginning to wake up to this demand for more members of the work force with data science skills.
Over the next decade we can expect to see growing investment and interest from all levels of the education spectrum in developing data science as a true standalone subject, and investments like that of the University of Michigan, which is set to invest $100m over the next five years in a new data science initiative, will increasingly become the norm.
If British businesses are to remain competitive in global markets they, and the education system that underpins the workforce, must recognise data science as not just a gimmick, but rather an integral part of business strategy and wider education agendas.
Sean Owen is director of data science at software firm Cloudera
Peak time growth funds show positive returns
Growth equity funds with 2007 vintages have outperformed expectations by producing 7.3 per cent returns, new Preqin data shows. Growth funds...
Harris + Hoole's three founders quit to refocus on 2006 coffee venture
Initially, Nick Tolley had claimed that Taylor St Baristas " a speciality coffee house he started with his two siblings in 2006 ? would not...
SMEs borrowing against diamond rings to invest in the business
The ongoing rise of alternative lending has seen those in need of cash for business investment leverage diamond rings worth...
Bradfords Gifts: Keeping things sweet through the Brexit transition
Real Business talks to James McGoldrick, co-owner of Bradfords Gifts, about how the company is navigating Brexit to ensure a...
Introducing the Philanthropic 30 2017: Meet the most caring companies in Britain
Why did we launch the Philanthropic 30" Why exactly have we been looking for Britain's most caring companies? Many a...
The importance of scent marketing for retail and hospitality sectors
When it comes to the retail and hospitality sectors, ICM's latest report showed there was a high demand for a fragrant...
Location insights can piece the consumer puzzle together
One would presume that in the run up to summer everyone is hitting the gym, avoiding pubs and eating more...
The Mary Portas publicity stunt
David Cameron commissioned Mary Portas to lead a review into the future of Britain's high streets last year. There were some rather...
Why jobs are still being created, while the economy shrinks
Recruitment, they say, is a barometer for economic prosperity: when the market gains the confidence to hire, green shoots start...
Five things we can learn from the Chinese
1. Build on the strength of your peopleIn China, the strengths of individuals are recognised and nurtured at a very...
More From Opinion
For GCSEs and business performance, I'll look for a Mo Farah not a Usain Bolt
Last week, the hot topic I was discussing was A-Levels, how we live in a ?university at all costs" world,...
Maintaining Britain's largest family firm: Secrets of the Queen's success
Although challenging at times, the Queen has always striven to maintain the stability of the family firm which has included...
Entrepreneurship must be at the heart of higher education
Technology has rewritten the rulebook of commerce, with the potential for businesses to go from bedroom project to multi-billion dollar...
No spring in my step
In the days of full-time motherhood, not only did half-term herald the nightmare of trying to juggle full-time work with...
HMRC's treatment of the self-employed is exposed for all to see
CEO of ContractorCalculator, Dave Chaplin says the self-employed are getting a bad deal from the Government, and the coronavirus crisis...
Changing currency: Post-Brexit concerns for SMEs
While markets have subsequently stabilised, the pound continues to trade below levels prior to the vote, reflecting the markets continuing...
Road repairs: don't just tarmac over the cracks
The additional £100m announced by
The problem with the Living Wage
Next week is Living Wage week. The campaign started in 2001 and was much supported by both David Cameron and...
FinTech: The future of finance
The seismic shifts caused by the financial crisis led many industry commentators to believe that the industry would experience a...
Jaguars leap into Formula E is one more example of the importance of sustainability
The company is set to become a manufacturer entry more than a decade after quitting Formula One (F1) in 2004,...


Walker & Dunlop, Inc. (NYSE: WD) (the "Company") announced today that it has hired Levi Brooker as senior vice president in its Multifamily Finance group. Based out of the Company's Los Angeles, California office, Mr. Brooker is responsible for originating multifamily loans primarily through Fannie Mae, Freddie Mac, and HUD. Mr. Brooker brings extensive experience structuring complex transactions including construction loans and loans with low income housing tax credits and tax exempt bonds. Throughout his career, he has assisted in financing over $1 billion of multifamily transactions.
Prior to joining Walker & Dunlop, Mr. Brooker served as senior vice president and loan officer for JLL's multifamily lending division. He previously worked for Oak Grove Capital and its predecessors from 2004 until 2015, when the entity merged with JLL. Mr. Brooker has experience financing loans backed by a wide array of multifamily property types, including affordable housing, manufactured housing, seniors housing, and student housing.


text:
Linebarger
beth@savannahvolleyball.com
Matt Linebarger
//CLUB DIRECTOR
Matt Linebarger assumed the role of Club Director in 2011. Linebarger has over two decades of successful coaching experience at the collegiate and club ranks.
Under Linebarger the club has grown from 11 teams that competed regionally to 26 teams with many traveling and competing nationally. Those teams have seen success at the national level with numerous top ten finishes. In addition to the teams success players have garnered individual attention from USA Volleyball's High Performance Program which is the pipeline to the women's national team (look under the history tab to see both the team and individual recognition by year). Linebarger has also played a key role in assisting over 40 athletes to continue their playing careers at the college level.
Prior to becoming the Club Director, Linebarger served as an assistant coach at the Savannah College of Art and Design (SCAD). While at SCAD, Linebarger coached a number of talented student-athletes. SCAD players collected eight all-conference titles to go along with a pair of All-Region selections.
Linebarger came to SCAD after serving as the head coach at Millsaps College, a NCAA Division III program located in Jackson, Mississippi.
During his coaching tenure, Linebarger has worked for some of the top coaches in the game. He got his start as an undergraduate assistant at Florida State University under Dr. Cecile Reynaud, who ranks 25th all-time in NCAA history with 635 victories. Also on staff was Sue Woodstra who has coached with the USA National Team as well as Arizona State University and the University of Pittsburgh.
Linebarger received his bachelor's degree in Sport Management from Florida State University in 2002 and his master's degree in Exercise Science from University of Louisiana-Monroe in 2005.
//CEO
Beth and her husband Matt assumed the roles of Co-directors of Club Savannah in 2011. While Matt handled the volleyball side of the club Beth handled all operations watching the club grow from 11 teams in 2011 to 26 teams, over 250 athletes, and 30 coaches in 2019.
With the expansion of the club Beth also played a pivotal role in bringing the club into the modern era with the implementation of a new club management system that streamlines all processes for both the parents and management.
In 2015 Beth was able to bring adidas in as the official sponsor of Club Savannah outfitting all teams with shoes, uniforms, and all things volleyball. Since then adidas has become the official sponsor of USA volleyball.
In 2017, Beth formed Savannah Sports Productions which hosts the Savannah Showdown at the Savannah Convention Center. In three years Beth has aided in growing the tournament from 90 teams to an expected 140 teams in the 2020 edition of the tournament.
Beth is a two time graduate of Louisiana Tech University (go bulldogs!) earning both her Bachelors in Family and Child Studies and Masters degrees in Family and Child Development.
//assistant director/recruiting coordinator
Hoffman first joined Club Savannah in 2015 from Richmond, Va where he coached at the high school and club level. Since then he has moved into a more permanent role as the assistant director and recruiting coordinator with the club.
Since joining Club Savannah Hoffman has also added college coaching to his resume first in the Spring of 2017 as a volunteer assistant with Armstrong State's program. Hoffman assisted in the running of drills and training after the merger between Armstrong State and Georgia Southern took place. For the 2018-2019 season Hoffman assisted at the College of Coastal Georgia where the team improved from 11-14 the year prior to 22-12 winning the conference tournament and advancing to the NAIA national tournament.
Hoffman's teams with Club Savannah have seen success at the national level with his 2018 17 Adidas team finishing 9th at AAU Nationals in Orlando. His 2019 17's team earned a bid to USAV Nationals in Indianapolis, IN winning the silver division finishing in 17th place nationally.
Since taking over as recruiting coordinator for the 2017-2018 season Hoffman has assisted in placing 17 athletes at the NCAA DI, DII, DIII, and NAIA levels respectively.
As a player Hoffman attended Nazareth College where he was part of a conference championship and a trip to the Final Four in 2010. After college Hoffman joined the Air Force where he served for six years.


text:
Swiss Federal Nuclear Safety Inspectorate ENSI
Activity (Definition)
Beznau Nuclear Power Plant
Classified radiation workers (Definition)
Core Shroud
Court decisions concerning the Mühleberg NPP
Deep geological repositories
Defense in depth
Doel and Tihange
ENSI Board
ENSI as an employer
ENSI as regulatory body
EU Stress Test
Events abroad
External deposit in Reitnau
Fukushima Action Plan
Gösgen Nuclear Power Plant
Human and organisational factors
IRRS Mission 2021
IRRS Mission 2011/2015
Interim storage facilities
Ionsiation (Definition)
Leibstadt Nuclear Power Plant
Measured Value about Swiss nuclear power plants
Mühleberg Nuclear Power Plant
Nuclear Facilities
Radiation dose (Definition)
Research reactors
Technical Forum on Safety
Technical Forum on Nuclear Power Plants
Ten Years on from Fukushima
Tritium (Definition)
Emergency Preparedness and Zone Plans
Dose rates
MADUK monitoring network
Dispersion modelling
INES levels
Alarm signals
Guidelines in force
Guidelines out for consultation
Oversight Reports
Radiation Protection Reports
Research and Experience Reports
Reports on Fukushima
ENSI's Remit
ENSI Executive Board
Guided Tours of the Mont Terri Rock Laboratory
Technical Safety Forum
Technical Forum on Nuclear Power Plants
Home » Posts » ENSI decides that Swiss nuclear plants should participate in Europe-wide peer review on ageing management
ENSI decides that Swiss nuclear plants should participate in Europe-wide peer review on ageing management
28 April 2017 News, Posts, Ageing, EU Stress Test, International Affairs, Topical Peer Review
Nuclear power plants in Switzerland are to take part in a Europe-wide peer review on ageing management this year. ENSI, the Swiss Federal Nuclear Safety Inspectorate, has decided that Swiss plants should participate in the EU Topical Peer Review.
Following on from the EU Stress Tests, the European Council decided that topical peer reviews should be carried out by nuclear power plants. Switzerland will also play a part in this review process on ageing management in nuclear power plants.
"By taking part in the 2017 Topical Peer Review, we hope to learn from experiences made in the field of ageing management in other European nuclear power plants," says ENSI Director General Hans Wanner. "Switzerland was one of the first countries to introduce ageing management," he added.
Systematic ageing monitoring in place for over 25 years
Swiss operators have been monitoring ageing components as part of a dedicated programme since 1991 and routinely inspect all safety and security-related components and structures to assess the effects of ageing.
As part of the Topical Peer Review, participating countries review the ageing management programmes of each other's nuclear power plants and use their findings as an opportunity to introduce potential improvements.
National report by the end of 2017
Each Swiss nuclear power plant will submit its report to ENSI by the summer of 2017. This should describe the ageing management programmes for the following components and structures:
electrical cables,
underground pipes,
reactor pressure vessels,
concrete structures in the reactor building.
ENSI will then use the reports from the nuclear plant operators to compile a consolidated Swiss national report.
Topical Peer Review process
The European Nuclear Safety Regulators Group ENSREG is to coordinate the 2017 Topical Peer Review. There are three phases in the review process:
National assessment: leading to a national report (to be published at the end of 2017).
Review of the submitted national reports (workshop in May 2018, final workshop report to be published in August 2018).
Implementation of the recommendations from the final report (implementation plan to be published in December 2018, with a report on the status of any implementation measures being published in December 2023).
EU launches peer reviews of ageing management of nuclear power plants
Topical Peer Review: Stakeholders Plan, Terms of Reference and WENRA Technical Specifications
EU Stress Test dossier
Ageing dossier
WENRA's statement on the importance of nuclear safety in the context of the current energy crisis
At its November 2022 plenary meeting, WENRA discussed the consequences of the current energy crisis on regulatory activities and issued a statement which highlights the importance of nuclear safety in this new challenging context.
Ukraine crisis takes centre stage at 66th IAEA General Conference
The 66th General Conference of the International Atomic Energy Agency (IAEA) took place in Vienna from 26 to 30 September 2022. The focus was on global nuclear safety and security as well as challenges arising from the Ukrainian crisis.
Review Conference on the Security of Nuclear Material
The first review conference of the Amended Convention on the Physical Protection of Nuclear Material took place from 28 March to 1 April 2022. Switzerland lobbied for a repeated review of the implementation of the Amended Convention, to be carried out in five years time as part of an IAEA conference. The Amended Convention on […]
Global nuclear safety is the focus of the 65th IAEA General Conference
The 65th General Conference of the International Atomic Energy Agency (IAEA) is taking place from 20 to 24 September. The focus is on nuclear safety, security and verification as well as the challenges arising from the COVID-19 pandemic.
IAEA Director General receives an insight into Swiss backfitting philosophy
ENSI experts gave IAEA Director General, Rafael Grossi, a guided tour of the Beznau nuclear power plant. Grossi was given a picture of the continuous improvements made to nuclear safety as laid down in the Vienna Declaration, in the setting of a Swiss example.
Nuclear security: Switzerland aims to strengthen cybersecurity
In a recent meeting, ENSI Director Hans Wanner and IAEA Director General Rafael Mariano Grossi discussed the latest issues and future challenges in nuclear safety and security. The meeting took place during the third International Conference on Nuclear Security organised by the IAEA in Vienna.
Switzerland commits to international cooperation in nuclear security
At the 62nd General Conference of the IAEA in Vienna, Switzerland last week committed itself to the strengthening of nuclear safety and security at the global level. ENSI also participated in bilateral discussions with international partners on the imortant topics of safety culture, emergency preparedness and the international security of nuclear installations and materials.
International experts provide Switzerland with recommendations for further improving security
The nuclear security regime is well established in Switzerland. That was the finding of an IPPAS team of experts of the International Atomic Energy Authority (IAEA) at the conclusion of their two-week mission.
Discussion on Nuclear Safety in the Context of the Nuclear Non-Proliferation Treaty
The Preparatory Committee for the 2020 Nuclear Non-Proliferation Treaty (NPT) Review Conference met last week in Geneva. In this context, Switzerland organized an international event in relation to nuclear safety and the peaceful use of nuclear energy.
THE REGULATORY AUTHORITY
ENSI, the Swiss Federal Nuclear Safety Inspectorate is the national regulatory authority with responsibility for nuclear energy.


text:
Vegetarian diets could help avert one-third of early deaths, Harvard researcher states
Vegetarians, rejoice!
The benefits of a vegetarian diet have greatly been underestimated, American physician and nutrition researcher Walter Willett told the audience at a recent conference. Giving up meat while still maintaining eggs and dairy in your diet does wonders for your health and could prevent up to one-third of all early deaths, Willett concludes.
"We have just been doing some calculations looking at the question of how much could we reduce mortality shifting towards a healthy, more plant-based diet, not necessarily totally vegan, and our estimates are about one third of early deaths could be prevented," he said.
"That's not even talking about physical activity or not smoking, and that's all deaths, not just cancer deaths. That's probably an underestimate as well as that doesn't take into account the fact that obesity is important and we control for obesity," he added.
Recent research has consistently shown that vegetarian diets, while far from being a panacea, are effective at reducing weight and maintaining health. However, Willett's study suggests that figures from previous studies gravely underestimate the benefits of such diets. For instance, the Office for National Statistics suggested that 141,000 deaths a year in Britain were preventable by renouncing meat, while the new research reports that about 200,000 lives could be saved each year in the UK if individuals removed meat from their diets.
He wasn't the only one to praise vegetarianism at the Unite to Cure Fourth International Vatican Conference, where he presented his results. Professor David Jenkins, of the University of Toronto, who is credited with developing the glycemic index, also praised the effect that a plant-based diet has on one's health.
The glycemic index is a rating system which shows how quickly each food affects your blood sugar (glucose) level when that food is eaten on its own, a unit widely used in nutritional and gastronomic guides
In a study on gorillas, Jenkins found that if gorillas are fed the equivalent of a human vegetarian diet, their cholesterol drops by 35% in only two weeks — the expected equivalent of a strong treatment with statins — a class of lipid-lowering medications. Having a simple diet change be as effective as a medical treatment is remarkable and shows just how important the vegetarian diet can be.
"That was quite dramatic," Jenkins said "We showed that there was no real difference between what we got with the diet and what we got with a statin." However, at least for now, the diet switch on its own is no substitute for medical treatment.
Even if you don't entirely give up meat, reducing meat intake can have extremely beneficial results. There is substantial research which shows that reducing meat from our diets (especially red meat) can help us be healthier and live longer.
Results have not yet been peer-reviewed.
Tags: nutritionvegetarianvegetarian diet