commit 482e719e877c6b03ff5e187f67bf3bbbe7393307 Author: Greg Burd Date: Mon Apr 29 09:35:35 2024 -0400 import diff --git a/Jake Moilanen's Linux Kernel Homepage.html b/Jake Moilanen's Linux Kernel Homepage.html new file mode 100644 index 0000000..780543b --- /dev/null +++ b/Jake Moilanen's Linux Kernel Homepage.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + +Jake Moilanen's Linux Kernel Homepage + + + + + + +
+
The Wayback Machine - https://web.archive.org/web/20060528133239/http://kernel.jakem.net:80/
+ + + +
+ + + + + + + + + + + + +
+
Jake Moilanen's Linux Kernel Homepage +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
   + + +
+ Genetic Library +
+ The genetic library patch uses a genetic algorithm to tweak the tunables of various schedulers.
+ As workloads change, the algorithm adjusts the tunables to optimize for performance. + The patch is very useful for specific workloads that are difficult to tune. +

+
  • Goal +
  • Current Plugins +
  • Future Work +
  • Performance +
  • Issues +
  • Why in kernel +
  • Config Locations +
  • Patches +

    + + Goal +
    + Tuning for workloads is tough, espcially when there are varying workloads. The goal of this patch + is that sys-admins and users never have to explicitly tune their system, but have it done autonomically. +
    + + + Currently I have plugins for: +
    +
  • Zaphod CPU scheduler +
  • Anticipatory IO scheduler +
  • Deadline IO scheduler (currently broken) +
  • + + Possible Future work: + +
    +
  • Incorporate pre-defined "sets of tunables". The child's genes would be a set known good of tunable + configurations, and the algorithm would just use which ever set performed the best. +
  • Save optimal tunings for workloads. Recognize changing workloads and switch to optimal settings. +
  • Make sure genes can be negative. +
  • Investigate using on packet scheduling. +
  • Investigate using on SMT scheduler. +
  • Investigate using Lamarckian Evolution on discrete parameters. +
  • + + Performance +
    +
    + On FFSB there was an average + improvement of 9%. On some + workloads, I saw a 23% + improvement. The only + degradation was in sequential + read, I saw a less than a 1%. + Which was expected since AS is + tuned for sequential read. + I'll put my formal paper up + soon w/ pretty graphics. +

    + On SpecJBB I've seen about a 1-5% gain on the Zaphod Scheduler plugin. +

    + On UnixBench I saw about a 2% gain for the file read/write/copy on the Anticipatory Scheduler. +

    + I've had no luck getting a performance improvement w/ the Deadline scheduler plugin. +
    + + Issues +
    +
    + Many times there is no IO while a child is running. The child that does not get IO is inadvertenly penalized.
    +
    +
    + Why have it in the kernel? +
    +
    +
  • Easier to hook +
  • Low latency and not have to go inbetween user/kernel (very important for short life cycle) +
  • Flexibility for the components to use the library +
  • Might have inconsistent results if was application, because it would be dependent on being scheduled, but itself was + in charge of modifying the scheduler. It may set the sched very wrong and never be scheduled. +
  • +
    + Config locations +
    +
  • genetic-library -  "Library Routines" -> "Genetic Library" +
  • genetic-as-sched - "Device Drivers" -> "Block IO" -> "Genetic Anticipatory IO Scheduler" +
  • genetic-zaphod-cpu-sched - "Library Routines" -> "Genetic Library - Zaphod CPU Scheduler" +
  • + Patches in development +

    + 2.6.12 Patches

    +

    + 2.6.11 Patches

    +
  • genetic-lib + - Base genetic library patch +
  • genetic-zaphod-cpu-sched + - Zaphod CPU scheduler plugin. + Depends on zaphod + 6.2 patch +
  • genetic-io-sched + - Base plugin for IO schedulers +
  • genetic-as-sched + - Anticipatory scheduler plugin. Depends on genetic-io-sched. +

    + 2.6.10 Patches

    +
  • genetic-lib + - Base genetic library patch +
  • genetic-zaphod-cpu-sched + - Zaphod CPU scheduler plugin. + Depends on zaphod + 6.2 patch +
  • genetic-io-sched + - Base plugin for IO schedulers +
  • genetic-as-sched + - Anticipatory scheduler plugin. Depends on genetic-io-sched. +

    + 2.6.9 Patches

    +
  • genetic-lib + - Base genetic library patch +
  • genetic-zaphod-cpu-sched + - Zaphod CPU scheduler plugin. Depends on zaphod patch +
  • genetic-io-sched + - Base plugin for IO schedulers +
  • genetic-as-sched + - Anticipatory scheduler plugin. Depends on genetic-io-sched. +
  • genetic-deadline-sched + - Deadline scheduler plugin. Depends on genetic-io-sched. (currently broken) +
  • +
    + + + + +
    +
    +
    + + + + + \ No newline at end of file diff --git a/Jake Moilanen's Linux Kernel Homepage_files/analytics.js b/Jake Moilanen's Linux Kernel Homepage_files/analytics.js new file mode 100644 index 0000000..ac86472 --- /dev/null +++ b/Jake Moilanen's Linux Kernel Homepage_files/analytics.js @@ -0,0 +1,474 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3.0 +/* eslint-disable no-var, semi, prefer-arrow-callback, prefer-template */ + +/** + * Collection of methods for sending analytics events to Archive.org's analytics server. + * + * These events are used for internal stats and sent (in anonymized form) to Google Analytics. + * + * @see analytics.md + * + * @type {Object} + */ +window.archive_analytics = (function defineArchiveAnalytics() { + // keep orignal Date object so as not to be affected by wayback's + // hijacking global Date object + var Date = window.Date; + var ARCHIVE_ANALYTICS_VERSION = 2; + var DEFAULT_SERVICE = 'ao_2'; + var NO_SAMPLING_SERVICE = 'ao_no_sampling'; // sends every event instead of a percentage + + var startTime = new Date(); + + /** + * @return {Boolean} + */ + function isPerformanceTimingApiSupported() { + return 'performance' in window && 'timing' in window.performance; + } + + /** + * Determines how many milliseconds elapsed between the browser starting to parse the DOM and + * the current time. + * + * Uses the Performance API or a fallback value if it's not available. + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/Performance_API + * + * @return {Number} + */ + function getLoadTime() { + var start; + + if (isPerformanceTimingApiSupported()) + start = window.performance.timing.domLoading; + else + start = startTime.getTime(); + + return new Date().getTime() - start; + } + + /** + * Determines how many milliseconds elapsed between the user navigating to the page and + * the current time. + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/Performance_API + * + * @return {Number|null} null if the browser doesn't support the Performance API + */ + function getNavToDoneTime() { + if (!isPerformanceTimingApiSupported()) + return null; + + return new Date().getTime() - window.performance.timing.navigationStart; + } + + /** + * Performs an arithmetic calculation on a string with a number and unit, while maintaining + * the unit. + * + * @param {String} original value to modify, with a unit + * @param {Function} doOperation accepts one Number parameter, returns a Number + * @returns {String} + */ + function computeWithUnit(original, doOperation) { + var number = parseFloat(original, 10); + var unit = original.replace(/(\d*\.\d+)|\d+/, ''); + + return doOperation(number) + unit; + } + + /** + * Computes the default font size of the browser. + * + * @returns {String|null} computed font-size with units (typically pixels), null if it cannot be computed + */ + function getDefaultFontSize() { + var fontSizeStr; + + if (!('getComputedStyle' in window)) + return null; + + var style = window.getComputedStyle(document.documentElement); + if (!style) + return null; + + fontSizeStr = style.fontSize; + + // Don't modify the value if tracking book reader. + if (document.querySelector('#BookReader')) + return fontSizeStr; + + return computeWithUnit(fontSizeStr, function reverseBootstrapFontSize(number) { + // Undo the 62.5% size applied in the Bootstrap CSS. + return number * 1.6; + }); + } + + /** + * Get the URL parameters for a given Location + * @param {Location} + * @return {Object} The URL parameters + */ + function getParams(location) { + if (!location) location = window.location; + var vars; + var i; + var pair; + var params = {}; + var query = location.search; + if (!query) return params; + vars = query.substring(1).split('&'); + for (i = 0; i < vars.length; i++) { + pair = vars[i].split('='); + params[pair[0]] = decodeURIComponent(pair[1]); + } + return params; + } + + function getMetaProp(name) { + var metaTag = document.querySelector('meta[property=' + name + ']'); + return metaTag ? metaTag.getAttribute('content') || null : null; + } + + var ArchiveAnalytics = { + /** + * @type {String|null} + */ + service: getMetaProp('service'), + mediaType: getMetaProp('mediatype'), + primaryCollection: getMetaProp('primary_collection'), + + /** + * Key-value pairs to send in pageviews (you can read this after a pageview to see what was + * sent). + * + * @type {Object} + */ + values: {}, + + /** + * Sends an analytics ping, preferably using navigator.sendBeacon() + * @param {Object} values + * @param {Function} [onload_callback] (deprecated) callback to invoke once ping to analytics server is done + * @param {Boolean} [augment_for_ao_site] (deprecated) if true, add some archive.org site-specific values + */ + send_ping: function send_ping(values, onload_callback, augment_for_ao_site) { + if (typeof window.navigator !== 'undefined' && typeof window.navigator.sendBeacon !== 'undefined') + this.send_ping_via_beacon(values); + else + this.send_ping_via_image(values); + }, + + /** + * Sends a ping via Beacon API + * NOTE: Assumes window.navigator.sendBeacon exists + * @param {Object} values Tracking parameters to pass + */ + send_ping_via_beacon: function send_ping_via_beacon(values) { + var url = this.generate_tracking_url(values || {}); + window.navigator.sendBeacon(url); + }, + + /** + * Sends a ping via Image object + * @param {Object} values Tracking parameters to pass + */ + send_ping_via_image: function send_ping_via_image(values) { + var url = this.generate_tracking_url(values || {}); + var loadtime_img = new Image(1, 1); + loadtime_img.src = url; + loadtime_img.alt = ''; + }, + + /** + * Construct complete tracking URL containing payload + * @param {Object} params Tracking parameters to pass + * @return {String} URL to use for tracking call + */ + generate_tracking_url: function generate_tracking_url(params) { + var baseUrl = '//analytics.archive.org/0.gif'; + var keys; + var outputParams = params; + var outputParamsArray = []; + + outputParams.service = outputParams.service || this.service || DEFAULT_SERVICE; + + // Build array of querystring parameters + keys = Object.keys(outputParams); + keys.forEach(function keyIteration(key) { + outputParamsArray.push(encodeURIComponent(key) + '=' + encodeURIComponent(outputParams[key])); + }); + outputParamsArray.push('version=' + ARCHIVE_ANALYTICS_VERSION); + outputParamsArray.push('count=' + (keys.length + 2)); // Include `version` and `count` in count + + return baseUrl + '?' + outputParamsArray.join('&'); + }, + + /** + * @param {int} page Page number + */ + send_scroll_fetch_event: function send_scroll_fetch_event(page) { + var additionalValues = { ev: page }; + var loadTime = getLoadTime(); + var navToDoneTime = getNavToDoneTime(); + if (loadTime) additionalValues.loadtime = loadTime; + if (navToDoneTime) additionalValues.nav_to_done_ms = navToDoneTime; + this.send_event('page_action', 'scroll_fetch', location.pathname, additionalValues); + }, + + send_scroll_fetch_base_event: function send_scroll_fetch_base_event() { + var additionalValues = {}; + var loadTime = getLoadTime(); + var navToDoneTime = getNavToDoneTime(); + if (loadTime) additionalValues.loadtime = loadTime; + if (navToDoneTime) additionalValues.nav_to_done_ms = navToDoneTime; + this.send_event('page_action', 'scroll_fetch_base', location.pathname, additionalValues); + }, + + /** + * @param {Object} [options] + * @param {String} [options.mediaType] + * @param {String} [options.mediaLanguage] + * @param {String} [options.page] The path portion of the page URL + */ + send_pageview: function send_pageview(options) { + var settings = options || {}; + + var defaultFontSize; + var loadTime = getLoadTime(); + var mediaType = settings.mediaType; + var primaryCollection = settings.primaryCollection; + var page = settings.page; + var navToDoneTime = getNavToDoneTime(); + + /** + * @return {String} + */ + function get_locale() { + if (navigator) { + if (navigator.language) + return navigator.language; + + else if (navigator.browserLanguage) + return navigator.browserLanguage; + + else if (navigator.systemLanguage) + return navigator.systemLanguage; + + else if (navigator.userLanguage) + return navigator.userLanguage; + } + return ''; + } + + defaultFontSize = getDefaultFontSize(); + + // Set field values + this.values.kind = 'pageview'; + this.values.timediff = (new Date().getTimezoneOffset()/60)*(-1); // *timezone* diff from UTC + this.values.locale = get_locale(); + this.values.referrer = (document.referrer == '' ? '-' : document.referrer); + + if (loadTime) + this.values.loadtime = loadTime; + + if (navToDoneTime) + this.values.nav_to_done_ms = navToDoneTime; + + if (settings.trackingId) { + this.values.ga_tid = settings.trackingId; + } + + /* START CUSTOM DIMENSIONS */ + if (defaultFontSize) + this.values.iaprop_fontSize = defaultFontSize; + + if ('devicePixelRatio' in window) + this.values.iaprop_devicePixelRatio = window.devicePixelRatio; + + if (mediaType) + this.values.iaprop_mediaType = mediaType; + + if (settings.mediaLanguage) { + this.values.iaprop_mediaLanguage = settings.mediaLanguage; + } + + if (primaryCollection) { + this.values.iaprop_primaryCollection = primaryCollection; + } + /* END CUSTOM DIMENSIONS */ + + if (page) + this.values.page = page; + + this.send_ping(this.values); + }, + + /** + * Sends a tracking "Event". + * @param {string} category + * @param {string} action + * @param {string} label + * @param {Object} additionalEventParams + */ + send_event: function send_event( + category, + action, + label, + additionalEventParams + ) { + if (!label) label = window.location.pathname; + if (!additionalEventParams) additionalEventParams = {}; + if (additionalEventParams.mediaLanguage) { + additionalEventParams.ga_cd4 = additionalEventParams.mediaLanguage; + delete additionalEventParams.mediaLanguage; + } + var eventParams = Object.assign( + { + kind: 'event', + ec: category, + ea: action, + el: label, + cache_bust: Math.random(), + }, + additionalEventParams + ); + this.send_ping(eventParams); + }, + + /** + * Sends every event instead of a small percentage. + * + * Use this sparingly as it can generate a lot of events. + * + * @param {string} category + * @param {string} action + * @param {string} label + * @param {Object} additionalEventParams + */ + send_event_no_sampling: function send_event_no_sampling( + category, + action, + label, + additionalEventParams + ) { + var extraParams = additionalEventParams || {}; + extraParams.service = NO_SAMPLING_SERVICE; + this.send_event(category, action, label, extraParams); + }, + + /** + * @param {Object} options see this.send_pageview options + */ + send_pageview_on_load: function send_pageview_on_load(options) { + var self = this; + window.addEventListener('load', function send_pageview_with_options() { + self.send_pageview(options); + }); + }, + + /** + * Handles tracking events passed in URL. + * Assumes category and action values are separated by a "|" character. + * NOTE: Uses the unsampled analytics property. Watch out for future high click links! + * @param {Location} + */ + process_url_events: function process_url_events(location) { + var eventValues; + var actionValue; + var eventValue = getParams(location).iax; + if (!eventValue) return; + eventValues = eventValue.split('|'); + actionValue = eventValues.length >= 1 ? eventValues[1] : ''; + this.send_event_no_sampling( + eventValues[0], + actionValue, + window.location.pathname + ); + }, + + /** + * Attaches handlers for event tracking. + * + * To enable click tracking for a link, add a `data-event-click-tracking` + * attribute containing the Google Analytics Event Category and Action, separated + * by a vertical pipe (|). + * e.g. `` + * + * To enable form submit tracking, add a `data-event-form-tracking` attribute + * to the `form` tag. + * e.g. `
    ` + * + * Additional tracking options can be added via a `data-event-tracking-options` + * parameter. This parameter, if included, should be a JSON string of the parameters. + * Valid parameters are: + * - service {string}: Corresponds to the Google Analytics property data values flow into + */ + set_up_event_tracking: function set_up_event_tracking() { + var self = this; + var clickTrackingAttributeName = 'event-click-tracking'; + var formTrackingAttributeName = 'event-form-tracking'; + var trackingOptionsAttributeName = 'event-tracking-options'; + + function handleAction(event, attributeName) { + var selector = '[data-' + attributeName + ']'; + var eventTarget = event.target; + if (!eventTarget) return; + var target = eventTarget.closest(selector); + if (!target) return; + var categoryAction; + var categoryActionParts; + var options; + categoryAction = target.dataset[toCamelCase(attributeName)]; + if (!categoryAction) return; + categoryActionParts = categoryAction.split('|'); + options = target.dataset[toCamelCase(trackingOptionsAttributeName)]; + options = options ? JSON.parse(options) : {}; + self.send_event( + categoryActionParts[0], + categoryActionParts[1], + categoryActionParts[2] || window.location.pathname, + options.service ? { service: options.service } : {} + ); + } + + function toCamelCase(str) { + return str.replace(/\W+(.)/g, function (match, chr) { + return chr.toUpperCase(); + }); + }; + + document.addEventListener('click', function(e) { + handleAction(e, clickTrackingAttributeName); + }); + + document.addEventListener('submit', function(e) { + handleAction(e, formTrackingAttributeName); + }); + }, + + /** + * @returns {Object[]} + */ + get_data_packets: function get_data_packets() { + return [this.values]; + }, + + /** + * Creates a tracking image for tracking JS compatibility. + * + * @param {string} type The type value for track_js_case in query params for 0.gif + */ + create_tracking_image: function create_tracking_image(type) { + this.send_ping_via_image({ + cache_bust: Math.random(), + kind: 'track_js', + track_js_case: type, + }); + } + }; + + return ArchiveAnalytics; +}()); +// @license-end diff --git a/Jake Moilanen's Linux Kernel Homepage_files/banner-styles.css b/Jake Moilanen's Linux Kernel Homepage_files/banner-styles.css new file mode 100644 index 0000000..0ab5af9 --- /dev/null +++ b/Jake Moilanen's Linux Kernel Homepage_files/banner-styles.css @@ -0,0 +1,507 @@ +@import 'record.css'; /* for SPN1 */ + +#wm-ipp-base { + height:65px;/* initial height just in case js code fails */ + padding:0; + margin:0; + border:none; + background:none transparent; +} +#wm-ipp { + z-index: 2147483647; +} +#wm-ipp, #wm-ipp * { + font-family:Lucida Grande, Helvetica, Arial, sans-serif; + font-size:12px; + line-height:1.2; + letter-spacing:0; + width:auto; + height:auto; + max-width:none; + max-height:none; + min-width:0 !important; + min-height:0; + outline:none; + float:none; + text-align:left; + border:none; + color: #000; + text-indent: 0; + position: initial; + background: none; +} +#wm-ipp div, #wm-ipp canvas { + display: block; +} +#wm-ipp div, #wm-ipp tr, #wm-ipp td, #wm-ipp a, #wm-ipp form { + padding:0; + margin:0; + border:none; + border-radius:0; + background-color:transparent; + background-image:none; + /*z-index:2147483640;*/ + height:auto; +} +#wm-ipp table { + border:none; + border-collapse:collapse; + margin:0; + padding:0; + width:auto; + font-size:inherit; +} +#wm-ipp form input { + padding:1px !important; + height:auto; + display:inline; + margin:0; + color: #000; + background: none #fff; + border: 1px solid #666; +} +#wm-ipp form input[type=submit] { + padding:0 8px !important; + margin:1px 0 1px 5px !important; + width:auto !important; + border: 1px solid #000 !important; + background: #fff !important; + color: #000 !important; +} +#wm-ipp form input[type=submit]:hover { + background: #eee !important; + cursor: pointer !important; +} +#wm-ipp form input[type=submit]:active { + transform: translateY(1px); +} +#wm-ipp a { + display: inline; +} +#wm-ipp a:hover{ + text-decoration:underline; +} +#wm-ipp a.wm-btn:hover { + text-decoration:none; + color:#ff0 !important; +} +#wm-ipp a.wm-btn:hover span { + color:#ff0 !important; +} +#wm-ipp #wm-ipp-inside { + margin: 0 6px; + border:5px solid #000; + border-top:none; + background-color:rgba(255,255,255,0.9); + -moz-box-shadow:1px 1px 4px #333; + -webkit-box-shadow:1px 1px 4px #333; + box-shadow:1px 1px 4px #333; + border-radius:0 0 8px 8px; +} +/* selectors are intentionally verbose to ensure priority */ +#wm-ipp #wm-logo { + padding:0 10px; + vertical-align:middle; + min-width:100px; + flex: 0 0 100px; +} +#wm-ipp .c { + padding-left: 4px; +} +#wm-ipp .c .u { + margin-top: 4px !important; +} +#wm-ipp .n { + padding:0 0 0 5px !important; + vertical-align: bottom; +} +#wm-ipp .n a { + text-decoration:none; + color:#33f; + font-weight:bold; +} +#wm-ipp .n .b { + padding:0 6px 0 0 !important; + text-align:right !important; + overflow:visible; + white-space:nowrap; + color:#99a; + vertical-align:middle; +} +#wm-ipp .n .y .b { + padding:0 6px 2px 0 !important; +} +#wm-ipp .n .c { + background:#000; + color:#ff0; + font-weight:bold; + padding:0 !important; + text-align:center; +} +#wm-ipp.hi .n td.c { + color:#ec008c; +} +#wm-ipp .n td.f { + padding:0 0 0 6px !important; + text-align:left !important; + overflow:visible; + white-space:nowrap; + color:#99a; + vertical-align:middle; +} +#wm-ipp .n tr.m td { + text-transform:uppercase; + white-space:nowrap; + padding:2px 0; +} +#wm-ipp .c .s { + padding:0 5px 0 0 !important; + vertical-align:bottom; +} +#wm-ipp #wm-nav-captures { + white-space: nowrap; +} +#wm-ipp .c .s a.t { + color:#33f; + font-weight:bold; + line-height: 1.8; +} +#wm-ipp .c .s div.r { + color: #666; + font-size:9px; + white-space:nowrap; +} +#wm-ipp .c .k { + padding-bottom:1px; +} +#wm-ipp .c .s { + padding:0 5px 2px 0 !important; +} +#wm-ipp td#displayMonthEl { + padding: 2px 0 !important; +} +#wm-ipp td#displayYearEl { + padding: 0 0 2px 0 !important; +} + +div#wm-ipp-sparkline { + position:relative;/* for positioning markers */ + white-space:nowrap; + background-color:#fff; + cursor:pointer; + line-height:0.9; +} +#sparklineImgId, #wm-sparkline-canvas { + position:relative; + z-index:9012; + max-width:none; +} +#wm-ipp-sparkline div.yt { + position:absolute; + z-index:9010 !important; + background-color:#ff0 !important; + top: 0; +} +#wm-ipp-sparkline div.mt { + position:absolute; + z-index:9013 !important; + background-color:#ec008c !important; + top: 0; +} +#wm-ipp .r { + margin-left: 4px; +} +#wm-ipp .r a { + color:#33f; + border:none; + position:relative; + background-color:transparent; + background-repeat:no-repeat !important; + background-position:100% 100% !important; + text-decoration: none; +} +#wm-ipp #wm-capinfo { + /* prevents notice div background from sticking into round corners of + #wm-ipp-inside */ + border-radius: 0 0 4px 4px; +} +#wm-ipp #wm-capinfo .c-logo { + display:block; + float:left; + margin-right:3px; + width:90px; + min-height:90px; + max-height: 290px; + border-radius:45px; + overflow:hidden; + background-position:50%; + background-size:auto 90px; + box-shadow: 0 0 2px 2px rgba(208,208,208,128) inset; +} +#wm-ipp #wm-capinfo .c-logo span { + display:inline-block; +} +#wm-ipp #wm-capinfo .c-logo img { + height:90px; + position:relative; + left:-50%; +} +#wm-ipp #wm-capinfo .wm-title { + font-size:130%; +} +#wm-ipp #wm-capinfo a.wm-selector { + display:inline-block; + color: #aaa; + text-decoration:none !important; + padding: 2px 8px; +} +#wm-ipp #wm-capinfo a.wm-selector.selected { + background-color:#666; +} +#wm-ipp #wm-capinfo a.wm-selector:hover { + color: #fff; +} +#wm-ipp #wm-capinfo.notice-only #wm-capinfo-collected-by, +#wm-ipp #wm-capinfo.notice-only #wm-capinfo-timestamps { + display: none; +} +#wm-ipp #wm-capinfo #wm-capinfo-notice .wm-capinfo-content { + background-color:#ff0; + padding:5px; + font-size:14px; + text-align:center; +} +#wm-ipp #wm-capinfo #wm-capinfo-notice .wm-capinfo-content * { + font-size:14px; + text-align:center; +} +#wm-ipp #wm-expand { + right: 1px; + bottom: -1px; + color: #ffffff; + background-color: #666 !important; + padding:0 5px 0 3px !important; + border-radius: 3px 3px 0 0 !important; +} +#wm-ipp #wm-expand span { + color: #ffffff; +} +#wm-ipp #wm-expand #wm-expand-icon { + display: inline-block; + transition: transform 0.5s; + transform-origin: 50% 45%; +} +#wm-ipp #wm-expand.wm-open #wm-expand-icon { + transform: rotate(180deg); +} +#wm-ipp #wmtb { + text-align:right; +} +#wm-ipp #wmtb #wmtbURL { + width: calc(100% - 45px); +} +#wm-ipp #wm-graph-anchor { + border-right:1px solid #ccc; +} +/* time coherence */ +html.wb-highlight { + box-shadow: inset 0 0 0 3px #a50e3a !important; +} +.wb-highlight { + outline: 3px solid #a50e3a !important; +} +#wm-ipp-print { + display:none !important; +} +@media print { +#wm-ipp-base { + display:none !important; +} +#wm-ipp-print { + display:block !important; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +} +@media (max-width:414px) { + #wm-ipp .xxs { + display:none !important; + } +} +@media (min-width:1055px) { +#wm-ipp #wm-graph-anchor { + display:block !important; +} +} +@media (max-width:1054px) { +#wm-ipp #wm-graph-anchor { + display:none !important; +} +} +@media (max-width:1163px) { +#wm-logo { + display:none !important; +} +} + +#wm-btns { + white-space: nowrap; + margin-top: -2px; +} + +#wm-btns #wm-save-snapshot-open { + margin-right: 7px; + top: -6px; +} + +#wm-btns #wm-sign-in { + box-sizing: content-box; + display: none; + margin-right: 7px; + top: -8px; + + /* + round border around sign in button + */ + border: 2px #000 solid; + border-radius: 14px; + padding-right: 2px; + padding-bottom: 2px; + width: 11px; + height: 11px; +} + +#wm-btns #wm-sign-in>.iconochive-person { + font-size: 12.5px; +} + +#wm-save-snapshot-open > .iconochive-web { + color:#000; + font-size:160%; +} + +#wm-ipp #wm-share { + display: flex; + align-items: flex-end; + justify-content: space-between; +} + +#wm-share > #wm-screenshot { + display: inline-block; + margin-right: 3px; + visibility: hidden; +} + +#wm-screenshot > .iconochive-image { + color:#000; + font-size:160%; +} + +#wm-share > #wm-video { + display: inline-block; + margin-right: 3px; + visibility: hidden; +} + +#wm-video > .iconochive-movies { + color: #000; + display: inline-block; + font-size: 150%; + margin-bottom: 2px; +} + +#wm-btns #wm-save-snapshot-in-progress { + display: none; + font-size:160%; + opacity: 0.5; + position: relative; + margin-right: 7px; + top: -5px; +} + +#wm-btns #wm-save-snapshot-success { + display: none; + color: green; + position: relative; + top: -7px; +} + +#wm-btns #wm-save-snapshot-fail { + display: none; + color: red; + position: relative; + top: -7px; +} + +.wm-icon-screen-shot { + background: url("../images/web-screenshot.svg") no-repeat !important; + background-size: contain !important; + width: 22px !important; + height: 19px !important; + + display: inline-block; +} +#donato { + /* transition effect is disable so as to simplify height adjustment */ + /*transition: height 0.5s;*/ + height: 0; + margin: 0; + padding: 0; + border-bottom: 1px solid #999 !important; +} +body.wm-modal { + height: auto !important; + overflow: hidden !important; +} +#donato #donato-base { + width: 100%; + height: 100%; + /*bottom: 0;*/ + margin: 0; + padding: 0; + position: absolute; + z-index: 2147483639; +} +body.wm-modal #donato #donato-base { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 2147483640; +} + +.wb-autocomplete-suggestions { + font-family: Lucida Grande, Helvetica, Arial, sans-serif; + font-size: 12px; + text-align: left; + cursor: default; + border: 1px solid #ccc; + border-top: 0; + background: #fff; + box-shadow: -1px 1px 3px rgba(0,0,0,.1); + position: absolute; + display: none; + z-index: 2147483647; + max-height: 254px; + overflow: hidden; + overflow-y: auto; + box-sizing: border-box; +} +.wb-autocomplete-suggestion { + position: relative; + padding: 0 .6em; + line-height: 23px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + font-size: 1.02em; + color: #333; +} +.wb-autocomplete-suggestion b { + font-weight: bold; +} +.wb-autocomplete-suggestion.selected { + background: #f0f0f0; +} diff --git a/Jake Moilanen's Linux Kernel Homepage_files/bundle-playback.js b/Jake Moilanen's Linux Kernel Homepage_files/bundle-playback.js new file mode 100644 index 0000000..fb272ef --- /dev/null +++ b/Jake Moilanen's Linux Kernel Homepage_files/bundle-playback.js @@ -0,0 +1,3 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0 +(()=>{"use strict";var e,t,n={createElementNS:document.createElementNS};var o=!0;function r(e){o=e}function i(e){try{r(!1),e()}finally{r(!0)}}function s(e){!function(e,t,n){if(n){var o=new Date;o.setTime(o.getTime()+24*n*60*60*1e3);var r="; expires="+o.toGMTString()}else r="";document.cookie=e+"="+t+r+"; path=/"}(e,"",-1)}function a(e){return a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},a(e)}function l(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:"src",n="_wm_".concat(t);return n in e.__proto__?e[n]:e[t]}g("Image","src"),g("Media","src"),g("Embed","src"),g("IFrame","src"),g("Script","src"),g("Link","href"),g("Anchor","href");var b=["January","February","March","April","May","June","July","August","September","October","November","December"],S=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],T={Y:function(e){return e.getUTCFullYear()},m:function(e){return e.getUTCMonth()+1},b:function(e){return S[e.getUTCMonth()]},B:function(e){return b[e.getUTCMonth()]},d:function(e){return e.getUTCDate()},H:function(e){return("0"+e.getUTCHours()).slice(-2)},M:function(e){return("0"+e.getUTCMinutes()).slice(-2)},S:function(e){return("0"+e.getUTCSeconds()).slice(-2)},"%":function(){return"%"}};function C(e){var t=function(e){return"number"==typeof e&&(e=e.toString()),[e.slice(-14,-10),e.slice(-10,-8),e.slice(-8,-6),e.slice(-6,-4),e.slice(-4,-2),e.slice(-2)]}(e);return new Date(Date.UTC(t[0],t[1]-1,t[2],t[3],t[4],t[5]))}function M(e){return S[e]}function _(e,t){return t.replace(/%./g,(function(t){var n=T[t[1]];return n?n(C(e)):t}))}var k=window.Date;function x(e,t){return(e=e.toString()).length>=t?e:"00000000".substring(0,t-e.length)+e}function E(e){for(var t=0,n=0;n3}(e)){var o=[];for(n=0;n=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,s=!0,a=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return s=e.done,e},e:function(e){a=!0,i=e},f:function(){try{s||null==n.return||n.return()}finally{if(a)throw i}}}}function L(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,o=new Array(t);n2&&void 0!==arguments[2]?arguments[2]:"src",i=window.location.origin,s=H(U(window,e));try{for(s.s();!(o=s.n()).done;){var l=o.value;if(!n||n(l)){var c=w(l,r);c&&!c.startsWith(t)&&c.startsWith(i)&&(c.startsWith("data:")||a.push(c))}}}catch(e){s.e(e)}finally{s.f()}}l("img"),l("frame"),l("iframe",(function(e){return"playback"!==e.id})),l("script"),l("link",(function(e){return"stylesheet"===e.rel}),"href");var c=a.filter((function(e,t,n){return n.indexOf(e)===t}));c.length>0?(s=0,c.map((function(e){e.match("^https?://")&&(s++,v("HEAD",e,(function(e){if(200==e.status){var t=e.getResponseHeader("Memento-Datetime");if(null==t)console.log("%s: no Memento-Datetime",u);else{var n=document.createElement("span"),a=function(e,t){var n=new Date(e).getTime()-t,o="";n<0?(o+="-",n=Math.abs(n)):o+="+";var r=!1;if(n<1e3)return{delta:n,text:"",highlight:r};var i=n,s=Math.floor(n/1e3/60/60/24/30/12);n-=1e3*s*60*60*24*30*12;var a=Math.floor(n/1e3/60/60/24/30);n-=1e3*a*60*60*24*30;var l=Math.floor(n/1e3/60/60/24);n-=1e3*l*60*60*24;var c=Math.floor(n/1e3/60/60);n-=1e3*c*60*60;var u=Math.floor(n/1e3/60);n-=1e3*u*60;var h=Math.floor(n/1e3),f=[];return s>1?(f.push(s+" years"),r=!0):1==s&&(f.push(s+" year"),r=!0),a>1?(f.push(a+" months"),r=!0):1==a&&(f.push(a+" month"),r=!0),l>1?f.push(l+" days"):1==l&&f.push(l+" day"),c>1?f.push(c+" hours"):1==c&&f.push(c+" hour"),u>1?f.push(u+" minutes"):1==u&&f.push(u+" minute"),h>1?f.push(h+" seconds"):1==h&&f.push(h+" second"),f.length>2&&(f=f.slice(0,2)),{delta:i,text:o+f.join(" "),highlight:r}}(t,i),l=a.highlight?"color:red;":"";n.innerHTML=" "+a.text,n.title=t,n.setAttribute("style",l);var c=e.getResponseHeader("Content-Type"),u=e.responseURL.replace(window.location.origin,""),h=document.createElement("a");h.innerHTML=u.split("/").splice(3).join("/"),h._wm_href=u,h.title=c,h.onmouseover=N,h.onmouseout=j;var f=document.createElement("div");f.setAttribute("data-delta",a.delta),f.appendChild(h),f.append(n),o.appendChild(f);var p=Array.prototype.slice.call(o.childNodes,0);p.sort((function(e,t){return t.getAttribute("data-delta")-e.getAttribute("data-delta")})),o.innerHTML="";for(var d=0,m=p.length;d0)for(var n=0;n0)for(var n=0;n0?this.sc.scrollTop=r+this.sc.suggestionHeight+o-this.sc.maxHeight:r<0&&(this.sc.scrollTop=r+o)}}},{key:"blurHandler",value:function(){var e=this;try{var t=this.root.querySelector(".wb-autocomplete-suggestions:hover")}catch(e){t=null}t?this.input!==document.activeElement&&setTimeout((function(){return e.focus()}),20):(this.last_val=this.input.value,this.sc.style.display="none",setTimeout((function(){return e.sc.style.display="none"}),350))}},{key:"suggest",value:function(e){var t=this.input.value;if(this.cache[t]=e,e.length&&t.length>=this.minChars){for(var n="",o=0;o40)&&13!=n&&27!=n){var o=this.input.value;if(o.length>=this.minChars){if(o!=this.last_val){if(this.last_val=o,clearTimeout(this.timer),this.cache){if(o in this.cache)return void this.suggest(this.cache[o]);for(var r=1;r'+e.replace(n,"$1")+""}},{key:"onSelect",value:function(e,t,n){}}]),e}(),$=function(){function e(t,n){P(this,e);var o=t.getRootNode();if(o.querySelector){var r="object"==I(t)?[t]:o.querySelectorAll(t);this.elems=r.map((function(e){return new Y(e,n)}))}}return q(e,[{key:"destroy",value:function(){for(;this.elems.length>0;)this.elems.pop().unload()}}]),e}();function J(e){return J="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},J(e)}function G(e,t){for(var n=0;n=0))}))}var t,n,o;return t=e,n=[{key:"save",value:function(e){var t,n,o,r;this.start(),t=this.url,n=this.timestamp,o=[],r=(r={failure:this.failure.bind(this),success:this.success.bind(this)})||{},v("POST","/__wb/web-archive/",(function(e){401===e.status?r.userNotLoggedIn&&r.userNotLoggedIn(e):e.status>=400?r.failure&&r.failure(e):r.success&&r.success(e)}),{"Content-Type":"application/json"},z.stringify({url:t,snapshot:n,tags:o||[]}))}},{key:"start",value:function(){this.hide(["wm-save-snapshot-fail","wm-save-snapshot-open","wm-save-snapshot-success"]),this.show(["wm-save-snapshot-in-progress"])}},{key:"failure",value:function(e){401==e.status?this.userNotLoggedIn(e):(this.hide(["wm-save-snapshot-in-progress","wm-save-snapshot-success"]),this.show(["wm-save-snapshot-fail","wm-save-snapshot-open"]),console.log("You have got an error."),console.log("If you think something wrong here please send it to support."),console.log('Response: "'+e.responseText+'"'),console.log('status: "'+e.status+'"'))}},{key:"success",value:function(e){this.hide(["wm-save-snapshot-fail","wm-save-snapshot-in-progress"]),this.show(["wm-save-snapshot-open","wm-save-snapshot-success"])}},{key:"enableSaveSnapshot",value:function(){arguments.length>0&&void 0!==arguments[0]&&!arguments[0]?(this.hide(["wm-save-snapshot-open","wm-save-snapshot-in-progress"]),this.show("wm-sign-in")):(this.show("wm-save-snapshot-open"),this.hide("wm-sign-in"))}},{key:"show",value:function(e){this.setDisplayStyle(e,"inline-block")}},{key:"hide",value:function(e){this.setDisplayStyle(e,"none")}},{key:"setDisplayStyle",value:function(e,t){var n=this;(y(e)?e:[e]).forEach((function(e){var o=n.el.getRootNode().getElementById(e);o&&(o.style.display=t)}))}}],n&&G(t.prototype,n),o&&G(t,o),Object.defineProperty(t,"prototype",{writable:!1}),e}();function K(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=function(e,t){if(!e)return;if("string"==typeof e)return Q(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return Q(e,t)}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var o=0,r=function(){};return{s:r,n:function(){return o>=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,s=!0,a=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return s=e.done,e},e:function(e){a=!0,i=e},f:function(){try{s||null==n.return||n.return()}finally{if(a)throw i}}}}function Q(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,o=new Array(t);n40)for(var t=0;t1?t-1:0),r=1;r0;)A.appendChild(L.children[0]);if(u)for(var O=0;O1?"captures":"capture");var f=_(r,"%d %b %Y");i!=r&&(f+=" - ".concat(_(i,"%d %b %Y")));var p=document.createElement("div");p.className="r",p.title="Timespan for captures of this URL",p.innerText=f,t.innerHTML="",t.appendChild(h),t.appendChild(p)}(o),function(e,t,n,o,r,i,s){var a=o.getContext("2d");if(a){a.fillStyle="#FFF";var l=(new k).getUTCFullYear(),c=t/(l-r+1),u=E(e.years),h=u[0],f=n/u[1];if(i>=r){var p=T(i);a.fillStyle="#FFFFA5",a.fillRect(p,0,c,n)}for(var d=r;d<=l;d++)p=T(d),a.beginPath(),a.moveTo(p,0),a.lineTo(p,n),a.lineWidth=1,a.strokeStyle="#CCC",a.stroke();s=parseInt(s)-1;for(var m=(c-1)/12,v=0;v0){var S=Math.ceil(b*f);a.fillStyle=d==i&&w==s?"#EC008C":"#000",a.fillRect(Math.round(g),Math.ceil(n-S),Math.ceil(m),Math.round(S))}g+=m}}}function T(e){return Math.ceil((e-r)*c)+.5}}(o,e,t,W,l,w,b)}}))}else{var X=new Image;X.src="/__wb/sparkline?url="+encodeURIComponent(s)+"&width="+e+"&height="+t+"&selected_year="+w+"&selected_month="+b+(r&&"&collection="+r||""),X.alt="sparkline",X.width=e,X.height=t,X.id="sparklineImgId",X.border="0",F.parentNode.replaceChild(X,F)}function Y(e){for(var t=[],n=e.length,o=0;o0&&i<60,i)}))}(e,t,(function(e,t){e?(ae("wm-screenshot").title="screen shot (delta: "+t+"s)",fe("wm-screenshot",!0)):fe("wm-screenshot",!1)}))}(s,le),h&&function(e,t){!function(e,t,n){var o="/web/"+t+"id_/http://wayback-metadata.archive.org/youtube-dl/"+e;v("GET",o,n)}(e,t,(function(e){if(e.status<300){var t=te.parse(e.responseText);fe("wm-video",!0),ae("wm-video").href=t.url,ae("wm-video").title="Video: "+t.title}else fe("wm-video",!1)}))}(s,le);var J=ae("wm-capinfo-notice");if(J)if("api"==J.getAttribute("source")){var G="https://wayback-api.archive.org/services/context/notices?url=".concat(encodeURIComponent(s),"×tamp=").concat(le);re(G,{credentials:"omit"}).then((function(e){return e.json()})).then((function(e){var t=e.status,n=e.notices;if("success"==t&&(null==n?void 0:n.length)>0)try{var o=document.createElement("div");o.setAttribute("style","background-color:#666;color:#fff;font-weight:bold;text-align:center"),o.textContent="NOTICE";var r=document.createElement("div");r.className="wm-capinfo-content";var s,a=K(n);try{var l=function(){var e=s.value;"string"==typeof e.notice&&i((function(){var t=document.createElement("div");t.innerHTML=e.notice,r.appendChild(t)}))};for(a.s();!(s=a.n()).done;)l()}catch(e){a.e(e)}finally{a.f()}J.appendChild(o),i((function(){return J.appendChild(r)})),ue(!0)}catch(e){console.error("failed to build content of %o - maybe notice text is malformed: %s",J,n)}}))}else ue(!0);new V(ae("wm-save-snapshot-open"),s,le)},ex:function(e){e.stopPropagation(),ue(!1)},ajax:v,sp:function(){return ce}}})(); +// @license-end diff --git a/Jake Moilanen's Linux Kernel Homepage_files/default.css b/Jake Moilanen's Linux Kernel Homepage_files/default.css new file mode 100644 index 0000000..ae54507 --- /dev/null +++ b/Jake Moilanen's Linux Kernel Homepage_files/default.css @@ -0,0 +1,117 @@ +BODY { + font-family: verdana, arial, helvetica, sans-serif, Trebuchet MS; + color: black; + background: #555555 +} + +A:link { + font-family: verdana, ari + helvetica, sans-serif, Trebuchet MS; +# font-size: 14pt; + color: black; + text-decoration: underline +} +A.nouline:link { + font-family: verdana, ari + helvetica, sans-serif, Trebuchet MS; + color:#CCC; + font-size:13px; + font-weight:normal; + background:#333; + linT„©ight:14px; + text-decoration: none +} +A.nouline:visited { + font-family: verdana, ari + helvetica, sans-serif, Trebuchet MS; + color:#CCC; + font-size:13px; + font-weight:normal; + background:#333; + linT„©ight:14px; + text-decoration: none +} +A.blue:link { + font-family: verdana, ari + helvetica, sans-serif, Trebuchet MS; +# font-size: 14pt; + color: #77aabb; + text-decoration: underline +} +A:unknown { + font-family: verdana, ari + helvetica, sans-serif, Trebuchet MS; + font-size: 14pt; +} +A:visited { + font-family: verdana, ari + helvetica, sans-serif, Trebuchet MS; + color: #aa99aa; + text-decoration: underline +} +A:hover { + font-family: verdana, ari + helvetica, sans-serif, Trebuchet MS; + color: white; + text-decoration: underline +} +TD { + font-family: verdana, arial, helvetica, sans-serif, Trebuchet MS; + font-size: 12pt; +} +TD.small { + font-family: verdana, arial, helvetica, sans-serif, Trebuchet MS; + font-size: 10pt; +} + +.menu_header { + font-family:verdana, arial, sans-serif; + color:#CCC; + font-size:13px; + font-weight:normal; + background:#333; + line-height:14px; + padding-left:10px; + padding-right:10px; + padding-top:10px; + padding-bottom:10px; +# border-left: 1px solid #b1b1b1; +# border-top: 1px solid #b1b1b1; + border-bottom: 1px solid #b1b1b1; +# border-right: 1px solid #b1b1b1; +} + +.menu_section { + font-family:verdana, arial, sans-serif; +# color:#CCC; + border-bottom: 1px solid #b1b1b1; + padding-left: 10px; + padding-right: 10px; + padding-top: 10px; + padding-bottom: 10px; + line-height: 14px; + font-size: 12px; + font-weight: normal; +} + + +/* + FILE ARCHIVED ON 03:14:21 Sep 01, 2005 AND RETRIEVED FROM THE + INTERNET ARCHIVE ON 12:49:07 Apr 29, 2024. + JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE. + + ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C. + SECTION 108(a)(3)). +*/ +/* +playback timings (ms): + captures_list: 0.768 + exclusion.robots: 0.111 + exclusion.robots.policy: 0.099 + cdx.remote: 0.083 + esindex: 0.03 + LoadShardBlock: 99.922 (3) + PetaboxLoader3.datanode: 67.4 (4) + PetaboxLoader3.resolve: 150.576 (2) + load_resource: 144.497 +*/ \ No newline at end of file diff --git a/Jake Moilanen's Linux Kernel Homepage_files/iconochive.css b/Jake Moilanen's Linux Kernel Homepage_files/iconochive.css new file mode 100644 index 0000000..7a95ea7 --- /dev/null +++ b/Jake Moilanen's Linux Kernel Homepage_files/iconochive.css @@ -0,0 +1,116 @@ +@font-face{font-family:'Iconochive-Regular';src:url('https://archive.org/includes/fonts/Iconochive-Regular.eot?-ccsheb');src:url('https://archive.org/includes/fonts/Iconochive-Regular.eot?#iefix-ccsheb') format('embedded-opentype'),url('https://archive.org/includes/fonts/Iconochive-Regular.woff?-ccsheb') format('woff'),url('https://archive.org/includes/fonts/Iconochive-Regular.ttf?-ccsheb') format('truetype'),url('https://archive.org/includes/fonts/Iconochive-Regular.svg?-ccsheb#Iconochive-Regular') format('svg');font-weight:normal;font-style:normal} +[class^="iconochive-"],[class*=" iconochive-"]{font-family:'Iconochive-Regular'!important;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale} +.iconochive-Uplevel:before{content:"\21b5"} +.iconochive-exit:before{content:"\1f6a3"} +.iconochive-beta:before{content:"\3b2"} +.iconochive-logo:before{content:"\1f3db"} +.iconochive-audio:before{content:"\1f568"} +.iconochive-movies:before{content:"\1f39e"} +.iconochive-software:before{content:"\1f4be"} +.iconochive-texts:before{content:"\1f56e"} +.iconochive-etree:before{content:"\1f3a4"} +.iconochive-image:before{content:"\1f5bc"} +.iconochive-web:before{content:"\1f5d4"} +.iconochive-collection:before{content:"\2211"} +.iconochive-folder:before{content:"\1f4c2"} +.iconochive-data:before{content:"\1f5c3"} +.iconochive-tv:before{content:"\1f4fa"} +.iconochive-article:before{content:"\1f5cf"} +.iconochive-question:before{content:"\2370"} +.iconochive-question-dark:before{content:"\3f"} +.iconochive-info:before{content:"\69"} +.iconochive-info-small:before{content:"\24d8"} +.iconochive-comment:before{content:"\1f5e9"} +.iconochive-comments:before{content:"\1f5ea"} +.iconochive-person:before{content:"\1f464"} +.iconochive-people:before{content:"\1f465"} +.iconochive-eye:before{content:"\1f441"} +.iconochive-rss:before{content:"\221e"} +.iconochive-time:before{content:"\1f551"} +.iconochive-quote:before{content:"\275d"} +.iconochive-disc:before{content:"\1f4bf"} +.iconochive-tv-commercial:before{content:"\1f4b0"} +.iconochive-search:before{content:"\1f50d"} +.iconochive-search-star:before{content:"\273d"} +.iconochive-tiles:before{content:"\229e"} +.iconochive-list:before{content:"\21f6"} +.iconochive-list-bulleted:before{content:"\2317"} +.iconochive-latest:before{content:"\2208"} +.iconochive-left:before{content:"\2c2"} +.iconochive-right:before{content:"\2c3"} +.iconochive-left-solid:before{content:"\25c2"} +.iconochive-right-solid:before{content:"\25b8"} +.iconochive-up-solid:before{content:"\25b4"} +.iconochive-down-solid:before{content:"\25be"} +.iconochive-dot:before{content:"\23e4"} +.iconochive-dots:before{content:"\25a6"} +.iconochive-columns:before{content:"\25af"} +.iconochive-sort:before{content:"\21d5"} +.iconochive-atoz:before{content:"\1f524"} +.iconochive-ztoa:before{content:"\1f525"} +.iconochive-upload:before{content:"\1f4e4"} +.iconochive-download:before{content:"\1f4e5"} +.iconochive-favorite:before{content:"\2605"} +.iconochive-heart:before{content:"\2665"} +.iconochive-play:before{content:"\25b6"} +.iconochive-play-framed:before{content:"\1f3ac"} +.iconochive-fullscreen:before{content:"\26f6"} +.iconochive-mute:before{content:"\1f507"} +.iconochive-unmute:before{content:"\1f50a"} +.iconochive-share:before{content:"\1f381"} +.iconochive-edit:before{content:"\270e"} +.iconochive-reedit:before{content:"\2710"} +.iconochive-gear:before{content:"\2699"} +.iconochive-remove-circle:before{content:"\274e"} +.iconochive-plus-circle:before{content:"\1f5d6"} +.iconochive-minus-circle:before{content:"\1f5d5"} +.iconochive-x:before{content:"\1f5d9"} +.iconochive-fork:before{content:"\22d4"} +.iconochive-trash:before{content:"\1f5d1"} +.iconochive-warning:before{content:"\26a0"} +.iconochive-flash:before{content:"\1f5f2"} +.iconochive-world:before{content:"\1f5fa"} +.iconochive-lock:before{content:"\1f512"} +.iconochive-unlock:before{content:"\1f513"} +.iconochive-twitter:before{content:"\1f426"} +.iconochive-facebook:before{content:"\66"} +.iconochive-googleplus:before{content:"\67"} +.iconochive-reddit:before{content:"\1f47d"} +.iconochive-tumblr:before{content:"\54"} +.iconochive-pinterest:before{content:"\1d4df"} +.iconochive-popcorn:before{content:"\1f4a5"} +.iconochive-email:before{content:"\1f4e7"} +.iconochive-embed:before{content:"\1f517"} +.iconochive-gamepad:before{content:"\1f579"} +.iconochive-Zoom_In:before{content:"\2b"} +.iconochive-Zoom_Out:before{content:"\2d"} +.iconochive-RSS:before{content:"\1f4e8"} +.iconochive-Light_Bulb:before{content:"\1f4a1"} +.iconochive-Add:before{content:"\2295"} +.iconochive-Tab_Activity:before{content:"\2318"} +.iconochive-Forward:before{content:"\23e9"} +.iconochive-Backward:before{content:"\23ea"} +.iconochive-No_Audio:before{content:"\1f508"} +.iconochive-Pause:before{content:"\23f8"} +.iconochive-No_Favorite:before{content:"\2606"} +.iconochive-Unike:before{content:"\2661"} +.iconochive-Song:before{content:"\266b"} +.iconochive-No_Flag:before{content:"\2690"} +.iconochive-Flag:before{content:"\2691"} +.iconochive-Done:before{content:"\2713"} +.iconochive-Check:before{content:"\2714"} +.iconochive-Refresh:before{content:"\27f3"} +.iconochive-Headphones:before{content:"\1f3a7"} +.iconochive-Chart:before{content:"\1f4c8"} +.iconochive-Bookmark:before{content:"\1f4d1"} +.iconochive-Documents:before{content:"\1f4da"} +.iconochive-Newspaper:before{content:"\1f4f0"} +.iconochive-Podcast:before{content:"\1f4f6"} +.iconochive-Radio:before{content:"\1f4fb"} +.iconochive-Cassette:before{content:"\1f4fc"} +.iconochive-Shuffle:before{content:"\1f500"} +.iconochive-Loop:before{content:"\1f501"} +.iconochive-Low_Audio:before{content:"\1f509"} +.iconochive-First:before{content:"\1f396"} +.iconochive-Invisible:before{content:"\1f576"} +.iconochive-Computer:before{content:"\1f5b3"} diff --git a/Jake Moilanen's Linux Kernel Homepage_files/ruffle.js b/Jake Moilanen's Linux Kernel Homepage_files/ruffle.js new file mode 100644 index 0000000..31ad077 --- /dev/null +++ b/Jake Moilanen's Linux Kernel Homepage_files/ruffle.js @@ -0,0 +1,3 @@ +/*! For license information please see ruffle.js.LICENSE.txt */ +(()=>{var e,n,t={297:(e,n,t)=>{e.exports=function e(n,t,r){function a(o,s){if(!t[o]){if(!n[o]){if(i)return i(o,!0);var l=new Error("Cannot find module '"+o+"'");throw l.code="MODULE_NOT_FOUND",l}var u=t[o]={exports:{}};n[o][0].call(u.exports,(function(e){return a(n[o][1][e]||e)}),u,u.exports,e,n,t,r)}return t[o].exports}for(var i=void 0,o=0;o>2,s=(3&n)<<4|t>>4,l=1>6:64,u=2>4,t=(15&o)<<4|(s=i.indexOf(e.charAt(u++)))>>2,r=(3&s)<<6|(l=i.indexOf(e.charAt(u++))),f[c++]=n,64!==s&&(f[c++]=t),64!==l&&(f[c++]=r);return f}},{"./support":30,"./utils":32}],2:[function(e,n,t){"use strict";var r=e("./external"),a=e("./stream/DataWorker"),i=e("./stream/Crc32Probe"),o=e("./stream/DataLengthProbe");function s(e,n,t,r,a){this.compressedSize=e,this.uncompressedSize=n,this.crc32=t,this.compression=r,this.compressedContent=a}s.prototype={getContentWorker:function(){var e=new a(r.Promise.resolve(this.compressedContent)).pipe(this.compression.uncompressWorker()).pipe(new o("data_length")),n=this;return e.on("end",(function(){if(this.streamInfo.data_length!==n.uncompressedSize)throw new Error("Bug : uncompressed data size mismatch")})),e},getCompressedWorker:function(){return new a(r.Promise.resolve(this.compressedContent)).withStreamInfo("compressedSize",this.compressedSize).withStreamInfo("uncompressedSize",this.uncompressedSize).withStreamInfo("crc32",this.crc32).withStreamInfo("compression",this.compression)}},s.createWorkerFrom=function(e,n,t){return e.pipe(new i).pipe(new o("uncompressedSize")).pipe(n.compressWorker(t)).pipe(new o("compressedSize")).withStreamInfo("compression",n)},n.exports=s},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(e,n,t){"use strict";var r=e("./stream/GenericWorker");t.STORE={magic:"\0\0",compressWorker:function(){return new r("STORE compression")},uncompressWorker:function(){return new r("STORE decompression")}},t.DEFLATE=e("./flate")},{"./flate":7,"./stream/GenericWorker":28}],4:[function(e,n,t){"use strict";var r=e("./utils"),a=function(){for(var e,n=[],t=0;t<256;t++){e=t;for(var r=0;r<8;r++)e=1&e?3988292384^e>>>1:e>>>1;n[t]=e}return n}();n.exports=function(e,n){return void 0!==e&&e.length?"string"!==r.getTypeOf(e)?function(e,n,t,r){var i=a,o=r+t;e^=-1;for(var s=r;s>>8^i[255&(e^n[s])];return-1^e}(0|n,e,e.length,0):function(e,n,t,r){var i=a,o=r+t;e^=-1;for(var s=r;s>>8^i[255&(e^n.charCodeAt(s))];return-1^e}(0|n,e,e.length,0):0}},{"./utils":32}],5:[function(e,n,t){"use strict";t.base64=!1,t.binary=!1,t.dir=!1,t.createFolders=!0,t.date=null,t.compression=null,t.compressionOptions=null,t.comment=null,t.unixPermissions=null,t.dosPermissions=null},{}],6:[function(e,n,t){"use strict";var r=null;r="undefined"!=typeof Promise?Promise:e("lie"),n.exports={Promise:r}},{lie:37}],7:[function(e,n,t){"use strict";var r="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,a=e("pako"),i=e("./utils"),o=e("./stream/GenericWorker"),s=r?"uint8array":"array";function l(e,n){o.call(this,"FlateWorker/"+e),this._pako=null,this._pakoAction=e,this._pakoOptions=n,this.meta={}}t.magic="\b\0",i.inherits(l,o),l.prototype.processChunk=function(e){this.meta=e.meta,null===this._pako&&this._createPako(),this._pako.push(i.transformTo(s,e.data),!1)},l.prototype.flush=function(){o.prototype.flush.call(this),null===this._pako&&this._createPako(),this._pako.push([],!0)},l.prototype.cleanUp=function(){o.prototype.cleanUp.call(this),this._pako=null},l.prototype._createPako=function(){this._pako=new a[this._pakoAction]({raw:!0,level:this._pakoOptions.level||-1});var e=this;this._pako.onData=function(n){e.push({data:n,meta:e.meta})}},t.compressWorker=function(e){return new l("Deflate",e)},t.uncompressWorker=function(){return new l("Inflate",{})}},{"./stream/GenericWorker":28,"./utils":32,pako:38}],8:[function(e,n,t){"use strict";function r(e,n){var t,r="";for(t=0;t>>=8;return r}function a(e,n,t,a,o,c){var d,f,m=e.file,h=e.compression,p=c!==s.utf8encode,v=i.transformTo("string",c(m.name)),g=i.transformTo("string",s.utf8encode(m.name)),b=m.comment,w=i.transformTo("string",c(b)),k=i.transformTo("string",s.utf8encode(b)),y=g.length!==m.name.length,x=k.length!==b.length,R="",_="",z="",S=m.dir,j=m.date,E={crc32:0,compressedSize:0,uncompressedSize:0};n&&!t||(E.crc32=e.crc32,E.compressedSize=e.compressedSize,E.uncompressedSize=e.uncompressedSize);var C=0;n&&(C|=8),p||!y&&!x||(C|=2048);var A=0,I=0;S&&(A|=16),"UNIX"===o?(I=798,A|=function(e,n){var t=e;return e||(t=n?16893:33204),(65535&t)<<16}(m.unixPermissions,S)):(I=20,A|=function(e){return 63&(e||0)}(m.dosPermissions)),d=j.getUTCHours(),d<<=6,d|=j.getUTCMinutes(),d<<=5,d|=j.getUTCSeconds()/2,f=j.getUTCFullYear()-1980,f<<=4,f|=j.getUTCMonth()+1,f<<=5,f|=j.getUTCDate(),y&&(_=r(1,1)+r(l(v),4)+g,R+="up"+r(_.length,2)+_),x&&(z=r(1,1)+r(l(w),4)+k,R+="uc"+r(z.length,2)+z);var F="";return F+="\n\0",F+=r(C,2),F+=h.magic,F+=r(d,2),F+=r(f,2),F+=r(E.crc32,4),F+=r(E.compressedSize,4),F+=r(E.uncompressedSize,4),F+=r(v.length,2),F+=r(R.length,2),{fileRecord:u.LOCAL_FILE_HEADER+F+v+R,dirRecord:u.CENTRAL_FILE_HEADER+r(I,2)+F+r(w.length,2)+"\0\0\0\0"+r(A,4)+r(a,4)+v+R+w}}var i=e("../utils"),o=e("../stream/GenericWorker"),s=e("../utf8"),l=e("../crc32"),u=e("../signature");function c(e,n,t,r){o.call(this,"ZipFileWorker"),this.bytesWritten=0,this.zipComment=n,this.zipPlatform=t,this.encodeFileName=r,this.streamFiles=e,this.accumulate=!1,this.contentBuffer=[],this.dirRecords=[],this.currentSourceOffset=0,this.entriesCount=0,this.currentFile=null,this._sources=[]}i.inherits(c,o),c.prototype.push=function(e){var n=e.meta.percent||0,t=this.entriesCount,r=this._sources.length;this.accumulate?this.contentBuffer.push(e):(this.bytesWritten+=e.data.length,o.prototype.push.call(this,{data:e.data,meta:{currentFile:this.currentFile,percent:t?(n+100*(t-r-1))/t:100}}))},c.prototype.openedSource=function(e){this.currentSourceOffset=this.bytesWritten,this.currentFile=e.file.name;var n=this.streamFiles&&!e.file.dir;if(n){var t=a(e,n,!1,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);this.push({data:t.fileRecord,meta:{percent:0}})}else this.accumulate=!0},c.prototype.closedSource=function(e){this.accumulate=!1;var n=this.streamFiles&&!e.file.dir,t=a(e,n,!0,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);if(this.dirRecords.push(t.dirRecord),n)this.push({data:function(e){return u.DATA_DESCRIPTOR+r(e.crc32,4)+r(e.compressedSize,4)+r(e.uncompressedSize,4)}(e),meta:{percent:100}});else for(this.push({data:t.fileRecord,meta:{percent:0}});this.contentBuffer.length;)this.push(this.contentBuffer.shift());this.currentFile=null},c.prototype.flush=function(){for(var e=this.bytesWritten,n=0;n=this.index;n--)t=(t<<8)+this.byteAt(n);return this.index+=e,t},readString:function(e){return r.transformTo("string",this.readData(e))},readData:function(){},lastIndexOfSignature:function(){},readAndCheckSignature:function(){},readDate:function(){var e=this.readInt(4);return new Date(Date.UTC(1980+(e>>25&127),(e>>21&15)-1,e>>16&31,e>>11&31,e>>5&63,(31&e)<<1))}},n.exports=a},{"../utils":32}],19:[function(e,n,t){"use strict";var r=e("./Uint8ArrayReader");function a(e){r.call(this,e)}e("../utils").inherits(a,r),a.prototype.readData=function(e){this.checkOffset(e);var n=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,n},n.exports=a},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(e,n,t){"use strict";var r=e("./DataReader");function a(e){r.call(this,e)}e("../utils").inherits(a,r),a.prototype.byteAt=function(e){return this.data.charCodeAt(this.zero+e)},a.prototype.lastIndexOfSignature=function(e){return this.data.lastIndexOf(e)-this.zero},a.prototype.readAndCheckSignature=function(e){return e===this.readData(4)},a.prototype.readData=function(e){this.checkOffset(e);var n=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,n},n.exports=a},{"../utils":32,"./DataReader":18}],21:[function(e,n,t){"use strict";var r=e("./ArrayReader");function a(e){r.call(this,e)}e("../utils").inherits(a,r),a.prototype.readData=function(e){if(this.checkOffset(e),0===e)return new Uint8Array(0);var n=this.data.subarray(this.zero+this.index,this.zero+this.index+e);return this.index+=e,n},n.exports=a},{"../utils":32,"./ArrayReader":17}],22:[function(e,n,t){"use strict";var r=e("../utils"),a=e("../support"),i=e("./ArrayReader"),o=e("./StringReader"),s=e("./NodeBufferReader"),l=e("./Uint8ArrayReader");n.exports=function(e){var n=r.getTypeOf(e);return r.checkSupport(n),"string"!==n||a.uint8array?"nodebuffer"===n?new s(e):a.uint8array?new l(r.transformTo("uint8array",e)):new i(r.transformTo("array",e)):new o(e)}},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(e,n,t){"use strict";t.LOCAL_FILE_HEADER="PK\x03\x04",t.CENTRAL_FILE_HEADER="PK\x01\x02",t.CENTRAL_DIRECTORY_END="PK\x05\x06",t.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK\x06\x07",t.ZIP64_CENTRAL_DIRECTORY_END="PK\x06\x06",t.DATA_DESCRIPTOR="PK\x07\b"},{}],24:[function(e,n,t){"use strict";var r=e("./GenericWorker"),a=e("../utils");function i(e){r.call(this,"ConvertWorker to "+e),this.destType=e}a.inherits(i,r),i.prototype.processChunk=function(e){this.push({data:a.transformTo(this.destType,e.data),meta:e.meta})},n.exports=i},{"../utils":32,"./GenericWorker":28}],25:[function(e,n,t){"use strict";var r=e("./GenericWorker"),a=e("../crc32");function i(){r.call(this,"Crc32Probe"),this.withStreamInfo("crc32",0)}e("../utils").inherits(i,r),i.prototype.processChunk=function(e){this.streamInfo.crc32=a(e.data,this.streamInfo.crc32||0),this.push(e)},n.exports=i},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(e,n,t){"use strict";var r=e("../utils"),a=e("./GenericWorker");function i(e){a.call(this,"DataLengthProbe for "+e),this.propName=e,this.withStreamInfo(e,0)}r.inherits(i,a),i.prototype.processChunk=function(e){if(e){var n=this.streamInfo[this.propName]||0;this.streamInfo[this.propName]=n+e.data.length}a.prototype.processChunk.call(this,e)},n.exports=i},{"../utils":32,"./GenericWorker":28}],27:[function(e,n,t){"use strict";var r=e("../utils"),a=e("./GenericWorker");function i(e){a.call(this,"DataWorker");var n=this;this.dataIsReady=!1,this.index=0,this.max=0,this.data=null,this.type="",this._tickScheduled=!1,e.then((function(e){n.dataIsReady=!0,n.data=e,n.max=e&&e.length||0,n.type=r.getTypeOf(e),n.isPaused||n._tickAndRepeat()}),(function(e){n.error(e)}))}r.inherits(i,a),i.prototype.cleanUp=function(){a.prototype.cleanUp.call(this),this.data=null},i.prototype.resume=function(){return!!a.prototype.resume.call(this)&&(!this._tickScheduled&&this.dataIsReady&&(this._tickScheduled=!0,r.delay(this._tickAndRepeat,[],this)),!0)},i.prototype._tickAndRepeat=function(){this._tickScheduled=!1,this.isPaused||this.isFinished||(this._tick(),this.isFinished||(r.delay(this._tickAndRepeat,[],this),this._tickScheduled=!0))},i.prototype._tick=function(){if(this.isPaused||this.isFinished)return!1;var e=null,n=Math.min(this.max,this.index+16384);if(this.index>=this.max)return this.end();switch(this.type){case"string":e=this.data.substring(this.index,n);break;case"uint8array":e=this.data.subarray(this.index,n);break;case"array":case"nodebuffer":e=this.data.slice(this.index,n)}return this.index=n,this.push({data:e,meta:{percent:this.max?this.index/this.max*100:0}})},n.exports=i},{"../utils":32,"./GenericWorker":28}],28:[function(e,n,t){"use strict";function r(e){this.name=e||"default",this.streamInfo={},this.generatedError=null,this.extraStreamInfo={},this.isPaused=!0,this.isFinished=!1,this.isLocked=!1,this._listeners={data:[],end:[],error:[]},this.previous=null}r.prototype={push:function(e){this.emit("data",e)},end:function(){if(this.isFinished)return!1;this.flush();try{this.emit("end"),this.cleanUp(),this.isFinished=!0}catch(e){this.emit("error",e)}return!0},error:function(e){return!this.isFinished&&(this.isPaused?this.generatedError=e:(this.isFinished=!0,this.emit("error",e),this.previous&&this.previous.error(e),this.cleanUp()),!0)},on:function(e,n){return this._listeners[e].push(n),this},cleanUp:function(){this.streamInfo=this.generatedError=this.extraStreamInfo=null,this._listeners=[]},emit:function(e,n){if(this._listeners[e])for(var t=0;t "+e:e}},n.exports=r},{}],29:[function(e,n,t){"use strict";var r=e("../utils"),a=e("./ConvertWorker"),i=e("./GenericWorker"),o=e("../base64"),s=e("../support"),l=e("../external"),u=null;if(s.nodestream)try{u=e("../nodejs/NodejsStreamOutputAdapter")}catch(e){}function c(e,n){return new l.Promise((function(t,a){var i=[],s=e._internalType,l=e._outputType,u=e._mimeType;e.on("data",(function(e,t){i.push(e),n&&n(t)})).on("error",(function(e){i=[],a(e)})).on("end",(function(){try{var e=function(e,n,t){switch(e){case"blob":return r.newBlob(r.transformTo("arraybuffer",n),t);case"base64":return o.encode(n);default:return r.transformTo(e,n)}}(l,function(e,n){var t,r=0,a=null,i=0;for(t=0;t>>6:(t<65536?n[o++]=224|t>>>12:(n[o++]=240|t>>>18,n[o++]=128|t>>>12&63),n[o++]=128|t>>>6&63),n[o++]=128|63&t);return n}(e)},t.utf8decode=function(e){return a.nodebuffer?r.transformTo("nodebuffer",e).toString("utf-8"):function(e){var n,t,a,i,o=e.length,l=new Array(2*o);for(n=t=0;n>10&1023,l[t++]=56320|1023&a)}return l.length!==t&&(l.subarray?l=l.subarray(0,t):l.length=t),r.applyFromCharCode(l)}(e=r.transformTo(a.uint8array?"uint8array":"array",e))},r.inherits(u,o),u.prototype.processChunk=function(e){var n=r.transformTo(a.uint8array?"uint8array":"array",e.data);if(this.leftOver&&this.leftOver.length){if(a.uint8array){var i=n;(n=new Uint8Array(i.length+this.leftOver.length)).set(this.leftOver,0),n.set(i,this.leftOver.length)}else n=this.leftOver.concat(n);this.leftOver=null}var o=function(e,n){var t;for((n=n||e.length)>e.length&&(n=e.length),t=n-1;0<=t&&128==(192&e[t]);)t--;return t<0||0===t?n:t+s[e[t]]>n?t:n}(n),l=n;o!==n.length&&(a.uint8array?(l=n.subarray(0,o),this.leftOver=n.subarray(o,n.length)):(l=n.slice(0,o),this.leftOver=n.slice(o,n.length))),this.push({data:t.utf8decode(l),meta:e.meta})},u.prototype.flush=function(){this.leftOver&&this.leftOver.length&&(this.push({data:t.utf8decode(this.leftOver),meta:{}}),this.leftOver=null)},t.Utf8DecodeWorker=u,r.inherits(c,o),c.prototype.processChunk=function(e){this.push({data:t.utf8encode(e.data),meta:e.meta})},t.Utf8EncodeWorker=c},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(e,n,t){"use strict";var r=e("./support"),a=e("./base64"),i=e("./nodejsUtils"),o=e("./external");function s(e){return e}function l(e,n){for(var t=0;t>8;this.dir=!!(16&this.externalFileAttributes),0==e&&(this.dosPermissions=63&this.externalFileAttributes),3==e&&(this.unixPermissions=this.externalFileAttributes>>16&65535),this.dir||"/"!==this.fileNameStr.slice(-1)||(this.dir=!0)},parseZIP64ExtraField:function(){if(this.extraFields[1]){var e=r(this.extraFields[1].value);this.uncompressedSize===a.MAX_VALUE_32BITS&&(this.uncompressedSize=e.readInt(8)),this.compressedSize===a.MAX_VALUE_32BITS&&(this.compressedSize=e.readInt(8)),this.localHeaderOffset===a.MAX_VALUE_32BITS&&(this.localHeaderOffset=e.readInt(8)),this.diskNumberStart===a.MAX_VALUE_32BITS&&(this.diskNumberStart=e.readInt(4))}},readExtraFields:function(e){var n,t,r,a=e.index+this.extraFieldsLength;for(this.extraFields||(this.extraFields={});e.index+4>>6:(t<65536?n[o++]=224|t>>>12:(n[o++]=240|t>>>18,n[o++]=128|t>>>12&63),n[o++]=128|t>>>6&63),n[o++]=128|63&t);return n},t.buf2binstring=function(e){return l(e,e.length)},t.binstring2buf=function(e){for(var n=new r.Buf8(e.length),t=0,a=n.length;t>10&1023,u[r++]=56320|1023&a)}return l(u,r)},t.utf8border=function(e,n){var t;for((n=n||e.length)>e.length&&(n=e.length),t=n-1;0<=t&&128==(192&e[t]);)t--;return t<0||0===t?n:t+o[e[t]]>n?t:n}},{"./common":41}],43:[function(e,n,t){"use strict";n.exports=function(e,n,t,r){for(var a=65535&e|0,i=e>>>16&65535|0,o=0;0!==t;){for(t-=o=2e3>>1:e>>>1;n[t]=e}return n}();n.exports=function(e,n,t,a){var i=r,o=a+t;e^=-1;for(var s=a;s>>8^i[255&(e^n[s])];return-1^e}},{}],46:[function(e,n,t){"use strict";var r,a=e("../utils/common"),i=e("./trees"),o=e("./adler32"),s=e("./crc32"),l=e("./messages"),u=0,c=4,d=0,f=-2,m=-1,h=4,p=2,v=8,g=9,b=286,w=30,k=19,y=2*b+1,x=15,R=3,_=258,z=_+R+1,S=42,j=113,E=1,C=2,A=3,I=4;function F(e,n){return e.msg=l[n],n}function O(e){return(e<<1)-(4e.avail_out&&(t=e.avail_out),0!==t&&(a.arraySet(e.output,n.pending_buf,n.pending_out,t,e.next_out),e.next_out+=t,n.pending_out+=t,e.total_out+=t,e.avail_out-=t,n.pending-=t,0===n.pending&&(n.pending_out=0))}function T(e,n){i._tr_flush_block(e,0<=e.block_start?e.block_start:-1,e.strstart-e.block_start,n),e.block_start=e.strstart,P(e.strm)}function q(e,n){e.pending_buf[e.pending++]=n}function M(e,n){e.pending_buf[e.pending++]=n>>>8&255,e.pending_buf[e.pending++]=255&n}function B(e,n){var t,r,a=e.max_chain_length,i=e.strstart,o=e.prev_length,s=e.nice_match,l=e.strstart>e.w_size-z?e.strstart-(e.w_size-z):0,u=e.window,c=e.w_mask,d=e.prev,f=e.strstart+_,m=u[i+o-1],h=u[i+o];e.prev_length>=e.good_match&&(a>>=2),s>e.lookahead&&(s=e.lookahead);do{if(u[(t=n)+o]===h&&u[t+o-1]===m&&u[t]===u[i]&&u[++t]===u[i+1]){i+=2,t++;do{}while(u[++i]===u[++t]&&u[++i]===u[++t]&&u[++i]===u[++t]&&u[++i]===u[++t]&&u[++i]===u[++t]&&u[++i]===u[++t]&&u[++i]===u[++t]&&u[++i]===u[++t]&&il&&0!=--a);return o<=e.lookahead?o:e.lookahead}function W(e){var n,t,r,i,l,u,c,d,f,m,h=e.w_size;do{if(i=e.window_size-e.lookahead-e.strstart,e.strstart>=h+(h-z)){for(a.arraySet(e.window,e.window,h,h,0),e.match_start-=h,e.strstart-=h,e.block_start-=h,n=t=e.hash_size;r=e.head[--n],e.head[n]=h<=r?r-h:0,--t;);for(n=t=h;r=e.prev[--n],e.prev[n]=h<=r?r-h:0,--t;);i+=h}if(0===e.strm.avail_in)break;if(u=e.strm,c=e.window,d=e.strstart+e.lookahead,m=void 0,(f=i)<(m=u.avail_in)&&(m=f),t=0===m?0:(u.avail_in-=m,a.arraySet(c,u.input,u.next_in,m,d),1===u.state.wrap?u.adler=o(u.adler,c,m,d):2===u.state.wrap&&(u.adler=s(u.adler,c,m,d)),u.next_in+=m,u.total_in+=m,m),e.lookahead+=t,e.lookahead+e.insert>=R)for(l=e.strstart-e.insert,e.ins_h=e.window[l],e.ins_h=(e.ins_h<=R&&(e.ins_h=(e.ins_h<=R)if(r=i._tr_tally(e,e.strstart-e.match_start,e.match_length-R),e.lookahead-=e.match_length,e.match_length<=e.max_lazy_match&&e.lookahead>=R){for(e.match_length--;e.strstart++,e.ins_h=(e.ins_h<=R&&(e.ins_h=(e.ins_h<=R&&e.match_length<=e.prev_length){for(a=e.strstart+e.lookahead-R,r=i._tr_tally(e,e.strstart-1-e.prev_match,e.prev_length-R),e.lookahead-=e.prev_length-1,e.prev_length-=2;++e.strstart<=a&&(e.ins_h=(e.ins_h<e.pending_buf_size-5&&(t=e.pending_buf_size-5);;){if(e.lookahead<=1){if(W(e),0===e.lookahead&&n===u)return E;if(0===e.lookahead)break}e.strstart+=e.lookahead,e.lookahead=0;var r=e.block_start+t;if((0===e.strstart||e.strstart>=r)&&(e.lookahead=e.strstart-r,e.strstart=r,T(e,!1),0===e.strm.avail_out))return E;if(e.strstart-e.block_start>=e.w_size-z&&(T(e,!1),0===e.strm.avail_out))return E}return e.insert=0,n===c?(T(e,!0),0===e.strm.avail_out?A:I):(e.strstart>e.block_start&&(T(e,!1),e.strm.avail_out),E)})),new N(4,4,8,4,L),new N(4,5,16,8,L),new N(4,6,32,32,L),new N(4,4,16,16,$),new N(8,16,32,32,$),new N(8,16,128,128,$),new N(8,32,128,256,$),new N(32,128,258,1024,$),new N(32,258,258,4096,$)],t.deflateInit=function(e,n){return J(e,n,v,15,8,0)},t.deflateInit2=J,t.deflateReset=H,t.deflateResetKeep=Z,t.deflateSetHeader=function(e,n){return e&&e.state?2!==e.state.wrap?f:(e.state.gzhead=n,d):f},t.deflate=function(e,n){var t,a,o,l;if(!e||!e.state||5>8&255),q(a,a.gzhead.time>>16&255),q(a,a.gzhead.time>>24&255),q(a,9===a.level?2:2<=a.strategy||a.level<2?4:0),q(a,255&a.gzhead.os),a.gzhead.extra&&a.gzhead.extra.length&&(q(a,255&a.gzhead.extra.length),q(a,a.gzhead.extra.length>>8&255)),a.gzhead.hcrc&&(e.adler=s(e.adler,a.pending_buf,a.pending,0)),a.gzindex=0,a.status=69):(q(a,0),q(a,0),q(a,0),q(a,0),q(a,0),q(a,9===a.level?2:2<=a.strategy||a.level<2?4:0),q(a,3),a.status=j);else{var m=v+(a.w_bits-8<<4)<<8;m|=(2<=a.strategy||a.level<2?0:a.level<6?1:6===a.level?2:3)<<6,0!==a.strstart&&(m|=32),m+=31-m%31,a.status=j,M(a,m),0!==a.strstart&&(M(a,e.adler>>>16),M(a,65535&e.adler)),e.adler=1}if(69===a.status)if(a.gzhead.extra){for(o=a.pending;a.gzindex<(65535&a.gzhead.extra.length)&&(a.pending!==a.pending_buf_size||(a.gzhead.hcrc&&a.pending>o&&(e.adler=s(e.adler,a.pending_buf,a.pending-o,o)),P(e),o=a.pending,a.pending!==a.pending_buf_size));)q(a,255&a.gzhead.extra[a.gzindex]),a.gzindex++;a.gzhead.hcrc&&a.pending>o&&(e.adler=s(e.adler,a.pending_buf,a.pending-o,o)),a.gzindex===a.gzhead.extra.length&&(a.gzindex=0,a.status=73)}else a.status=73;if(73===a.status)if(a.gzhead.name){o=a.pending;do{if(a.pending===a.pending_buf_size&&(a.gzhead.hcrc&&a.pending>o&&(e.adler=s(e.adler,a.pending_buf,a.pending-o,o)),P(e),o=a.pending,a.pending===a.pending_buf_size)){l=1;break}l=a.gzindexo&&(e.adler=s(e.adler,a.pending_buf,a.pending-o,o)),0===l&&(a.gzindex=0,a.status=91)}else a.status=91;if(91===a.status)if(a.gzhead.comment){o=a.pending;do{if(a.pending===a.pending_buf_size&&(a.gzhead.hcrc&&a.pending>o&&(e.adler=s(e.adler,a.pending_buf,a.pending-o,o)),P(e),o=a.pending,a.pending===a.pending_buf_size)){l=1;break}l=a.gzindexo&&(e.adler=s(e.adler,a.pending_buf,a.pending-o,o)),0===l&&(a.status=103)}else a.status=103;if(103===a.status&&(a.gzhead.hcrc?(a.pending+2>a.pending_buf_size&&P(e),a.pending+2<=a.pending_buf_size&&(q(a,255&e.adler),q(a,e.adler>>8&255),e.adler=0,a.status=j)):a.status=j),0!==a.pending){if(P(e),0===e.avail_out)return a.last_flush=-1,d}else if(0===e.avail_in&&O(n)<=O(t)&&n!==c)return F(e,-5);if(666===a.status&&0!==e.avail_in)return F(e,-5);if(0!==e.avail_in||0!==a.lookahead||n!==u&&666!==a.status){var h=2===a.strategy?function(e,n){for(var t;;){if(0===e.lookahead&&(W(e),0===e.lookahead)){if(n===u)return E;break}if(e.match_length=0,t=i._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++,t&&(T(e,!1),0===e.strm.avail_out))return E}return e.insert=0,n===c?(T(e,!0),0===e.strm.avail_out?A:I):e.last_lit&&(T(e,!1),0===e.strm.avail_out)?E:C}(a,n):3===a.strategy?function(e,n){for(var t,r,a,o,s=e.window;;){if(e.lookahead<=_){if(W(e),e.lookahead<=_&&n===u)return E;if(0===e.lookahead)break}if(e.match_length=0,e.lookahead>=R&&0e.lookahead&&(e.match_length=e.lookahead)}if(e.match_length>=R?(t=i._tr_tally(e,1,e.match_length-R),e.lookahead-=e.match_length,e.strstart+=e.match_length,e.match_length=0):(t=i._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++),t&&(T(e,!1),0===e.strm.avail_out))return E}return e.insert=0,n===c?(T(e,!0),0===e.strm.avail_out?A:I):e.last_lit&&(T(e,!1),0===e.strm.avail_out)?E:C}(a,n):r[a.level].func(a,n);if(h!==A&&h!==I||(a.status=666),h===E||h===A)return 0===e.avail_out&&(a.last_flush=-1),d;if(h===C&&(1===n?i._tr_align(a):5!==n&&(i._tr_stored_block(a,0,0,!1),3===n&&(D(a.head),0===a.lookahead&&(a.strstart=0,a.block_start=0,a.insert=0))),P(e),0===e.avail_out))return a.last_flush=-1,d}return n!==c?d:a.wrap<=0?1:(2===a.wrap?(q(a,255&e.adler),q(a,e.adler>>8&255),q(a,e.adler>>16&255),q(a,e.adler>>24&255),q(a,255&e.total_in),q(a,e.total_in>>8&255),q(a,e.total_in>>16&255),q(a,e.total_in>>24&255)):(M(a,e.adler>>>16),M(a,65535&e.adler)),P(e),0=t.w_size&&(0===s&&(D(t.head),t.strstart=0,t.block_start=0,t.insert=0),m=new a.Buf8(t.w_size),a.arraySet(m,n,h-t.w_size,t.w_size,0),n=m,h=t.w_size),l=e.avail_in,u=e.next_in,c=e.input,e.avail_in=h,e.next_in=0,e.input=n,W(t);t.lookahead>=R;){for(r=t.strstart,i=t.lookahead-(R-1);t.ins_h=(t.ins_h<>>=k=w>>>24,h-=k,0==(k=w>>>16&255))S[i++]=65535&w;else{if(!(16&k)){if(0==(64&k)){w=p[(65535&w)+(m&(1<>>=k,h-=k),h<15&&(m+=z[r++]<>>=k=w>>>24,h-=k,!(16&(k=w>>>16&255))){if(0==(64&k)){w=v[(65535&w)+(m&(1<>>=k,h-=k,(k=i-o)>3,m&=(1<<(h-=y<<3))-1,e.next_in=r,e.next_out=i,e.avail_in=r>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)}function v(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new r.Buf16(320),this.work=new r.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function g(e){var n;return e&&e.state?(n=e.state,e.total_in=e.total_out=n.total=0,e.msg="",n.wrap&&(e.adler=1&n.wrap),n.mode=f,n.last=0,n.havedict=0,n.dmax=32768,n.head=null,n.hold=0,n.bits=0,n.lencode=n.lendyn=new r.Buf32(m),n.distcode=n.distdyn=new r.Buf32(h),n.sane=1,n.back=-1,c):d}function b(e){var n;return e&&e.state?((n=e.state).wsize=0,n.whave=0,n.wnext=0,g(e)):d}function w(e,n){var t,r;return e&&e.state?(r=e.state,n<0?(t=0,n=-n):(t=1+(n>>4),n<48&&(n&=15)),n&&(n<8||15=o.wsize?(r.arraySet(o.window,n,t-o.wsize,o.wsize,0),o.wnext=0,o.whave=o.wsize):(a<(i=o.wsize-o.wnext)&&(i=a),r.arraySet(o.window,n,t-a,i,o.wnext),(a-=i)?(r.arraySet(o.window,n,t-a,a,0),o.wnext=a,o.whave=o.wsize):(o.wnext+=i,o.wnext===o.wsize&&(o.wnext=0),o.whave>>8&255,t.check=i(t.check,W,2,0),y=k=0,t.mode=2;break}if(t.flags=0,t.head&&(t.head.done=!1),!(1&t.wrap)||(((255&k)<<8)+(k>>8))%31){e.msg="incorrect header check",t.mode=30;break}if(8!=(15&k)){e.msg="unknown compression method",t.mode=30;break}if(y-=4,P=8+(15&(k>>>=4)),0===t.wbits)t.wbits=P;else if(P>t.wbits){e.msg="invalid window size",t.mode=30;break}t.dmax=1<>8&1),512&t.flags&&(W[0]=255&k,W[1]=k>>>8&255,t.check=i(t.check,W,2,0)),y=k=0,t.mode=3;case 3:for(;y<32;){if(0===b)break e;b--,k+=m[v++]<>>8&255,W[2]=k>>>16&255,W[3]=k>>>24&255,t.check=i(t.check,W,4,0)),y=k=0,t.mode=4;case 4:for(;y<16;){if(0===b)break e;b--,k+=m[v++]<>8),512&t.flags&&(W[0]=255&k,W[1]=k>>>8&255,t.check=i(t.check,W,2,0)),y=k=0,t.mode=5;case 5:if(1024&t.flags){for(;y<16;){if(0===b)break e;b--,k+=m[v++]<>>8&255,t.check=i(t.check,W,2,0)),y=k=0}else t.head&&(t.head.extra=null);t.mode=6;case 6:if(1024&t.flags&&(b<(S=t.length)&&(S=b),S&&(t.head&&(P=t.head.extra_len-t.length,t.head.extra||(t.head.extra=new Array(t.head.extra_len)),r.arraySet(t.head.extra,m,v,S,P)),512&t.flags&&(t.check=i(t.check,m,S,v)),b-=S,v+=S,t.length-=S),t.length))break e;t.length=0,t.mode=7;case 7:if(2048&t.flags){if(0===b)break e;for(S=0;P=m[v+S++],t.head&&P&&t.length<65536&&(t.head.name+=String.fromCharCode(P)),P&&S>9&1,t.head.done=!0),e.adler=t.check=0,t.mode=12;break;case 10:for(;y<32;){if(0===b)break e;b--,k+=m[v++]<>>=7&y,y-=7&y,t.mode=27;break}for(;y<3;){if(0===b)break e;b--,k+=m[v++]<>>=1)){case 0:t.mode=14;break;case 1:if(_(t),t.mode=20,6!==n)break;k>>>=2,y-=2;break e;case 2:t.mode=17;break;case 3:e.msg="invalid block type",t.mode=30}k>>>=2,y-=2;break;case 14:for(k>>>=7&y,y-=7&y;y<32;){if(0===b)break e;b--,k+=m[v++]<>>16^65535)){e.msg="invalid stored block lengths",t.mode=30;break}if(t.length=65535&k,y=k=0,t.mode=15,6===n)break e;case 15:t.mode=16;case 16:if(S=t.length){if(b>>=5,y-=5,t.ndist=1+(31&k),k>>>=5,y-=5,t.ncode=4+(15&k),k>>>=4,y-=4,286>>=3,y-=3}for(;t.have<19;)t.lens[L[t.have++]]=0;if(t.lencode=t.lendyn,t.lenbits=7,q={bits:t.lenbits},T=s(0,t.lens,0,19,t.lencode,0,t.work,q),t.lenbits=q.bits,T){e.msg="invalid code lengths set",t.mode=30;break}t.have=0,t.mode=19;case 19:for(;t.have>>16&255,I=65535&B,!((C=B>>>24)<=y);){if(0===b)break e;b--,k+=m[v++]<>>=C,y-=C,t.lens[t.have++]=I;else{if(16===I){for(M=C+2;y>>=C,y-=C,0===t.have){e.msg="invalid bit length repeat",t.mode=30;break}P=t.lens[t.have-1],S=3+(3&k),k>>>=2,y-=2}else if(17===I){for(M=C+3;y>>=C)),k>>>=3,y-=3}else{for(M=C+7;y>>=C)),k>>>=7,y-=7}if(t.have+S>t.nlen+t.ndist){e.msg="invalid bit length repeat",t.mode=30;break}for(;S--;)t.lens[t.have++]=P}}if(30===t.mode)break;if(0===t.lens[256]){e.msg="invalid code -- missing end-of-block",t.mode=30;break}if(t.lenbits=9,q={bits:t.lenbits},T=s(l,t.lens,0,t.nlen,t.lencode,0,t.work,q),t.lenbits=q.bits,T){e.msg="invalid literal/lengths set",t.mode=30;break}if(t.distbits=6,t.distcode=t.distdyn,q={bits:t.distbits},T=s(u,t.lens,t.nlen,t.ndist,t.distcode,0,t.work,q),t.distbits=q.bits,T){e.msg="invalid distances set",t.mode=30;break}if(t.mode=20,6===n)break e;case 20:t.mode=21;case 21:if(6<=b&&258<=w){e.next_out=g,e.avail_out=w,e.next_in=v,e.avail_in=b,t.hold=k,t.bits=y,o(e,R),g=e.next_out,h=e.output,w=e.avail_out,v=e.next_in,m=e.input,b=e.avail_in,k=t.hold,y=t.bits,12===t.mode&&(t.back=-1);break}for(t.back=0;A=(B=t.lencode[k&(1<>>16&255,I=65535&B,!((C=B>>>24)<=y);){if(0===b)break e;b--,k+=m[v++]<>F)])>>>16&255,I=65535&B,!(F+(C=B>>>24)<=y);){if(0===b)break e;b--,k+=m[v++]<>>=F,y-=F,t.back+=F}if(k>>>=C,y-=C,t.back+=C,t.length=I,0===A){t.mode=26;break}if(32&A){t.back=-1,t.mode=12;break}if(64&A){e.msg="invalid literal/length code",t.mode=30;break}t.extra=15&A,t.mode=22;case 22:if(t.extra){for(M=t.extra;y>>=t.extra,y-=t.extra,t.back+=t.extra}t.was=t.length,t.mode=23;case 23:for(;A=(B=t.distcode[k&(1<>>16&255,I=65535&B,!((C=B>>>24)<=y);){if(0===b)break e;b--,k+=m[v++]<>F)])>>>16&255,I=65535&B,!(F+(C=B>>>24)<=y);){if(0===b)break e;b--,k+=m[v++]<>>=F,y-=F,t.back+=F}if(k>>>=C,y-=C,t.back+=C,64&A){e.msg="invalid distance code",t.mode=30;break}t.offset=I,t.extra=15&A,t.mode=24;case 24:if(t.extra){for(M=t.extra;y>>=t.extra,y-=t.extra,t.back+=t.extra}if(t.offset>t.dmax){e.msg="invalid distance too far back",t.mode=30;break}t.mode=25;case 25:if(0===w)break e;if(S=R-w,t.offset>S){if((S=t.offset-S)>t.whave&&t.sane){e.msg="invalid distance too far back",t.mode=30;break}j=S>t.wnext?(S-=t.wnext,t.wsize-S):t.wnext-S,S>t.length&&(S=t.length),E=t.window}else E=h,j=g-t.offset,S=t.length;for(wb?(k=q[M+d[_]],O[D+d[_]]):(k=96,0),m=1<>C)+(h-=m)]=w<<24|k<<16|y|0,0!==h;);for(m=1<>=1;if(0!==m?(F&=m-1,F+=m):F=0,_++,0==--P[R]){if(R===S)break;R=n[t+d[_]]}if(j>>7)]}function q(e,n){e.pending_buf[e.pending++]=255&n,e.pending_buf[e.pending++]=n>>>8&255}function M(e,n,t){e.bi_valid>p-t?(e.bi_buf|=n<>p-e.bi_valid,e.bi_valid+=t-p):(e.bi_buf|=n<>>=1,t<<=1,0<--n;);return t>>>1}function L(e,n,t){var r,a,i=new Array(h+1),o=0;for(r=1;r<=h;r++)i[r]=o=o+t[r-1]<<1;for(a=0;a<=n;a++){var s=e[2*a+1];0!==s&&(e[2*a]=W(i[s]++,s))}}function $(e){var n;for(n=0;n>1;1<=t;t--)Z(e,i,t);for(a=l;t=e.heap[1],e.heap[1]=e.heap[e.heap_len--],Z(e,i,1),r=e.heap[1],e.heap[--e.heap_max]=t,e.heap[--e.heap_max]=r,i[2*a]=i[2*t]+i[2*r],e.depth[a]=(e.depth[t]>=e.depth[r]?e.depth[t]:e.depth[r])+1,i[2*t+1]=i[2*r+1]=a,e.heap[1]=a++,Z(e,i,1),2<=e.heap_len;);e.heap[--e.heap_max]=e.heap[1],function(e,n){var t,r,a,i,o,s,l=n.dyn_tree,u=n.max_code,c=n.stat_desc.static_tree,d=n.stat_desc.has_stree,f=n.stat_desc.extra_bits,p=n.stat_desc.extra_base,v=n.stat_desc.max_length,g=0;for(i=0;i<=h;i++)e.bl_count[i]=0;for(l[2*e.heap[e.heap_max]+1]=0,t=e.heap_max+1;t>=7;r>>=1)if(1&t&&0!==e.dyn_ltree[2*n])return a;if(0!==e.dyn_ltree[18]||0!==e.dyn_ltree[20]||0!==e.dyn_ltree[26])return i;for(n=32;n>>3,(s=e.static_len+3+7>>>3)<=o&&(o=s)):o=s=t+5,t+4<=o&&-1!==n?Y(e,n,t,r):4===e.strategy||s===o?(M(e,2+(r?1:0),3),H(e,z,S)):(M(e,4+(r?1:0),3),function(e,n,t,r){var a;for(M(e,n-257,5),M(e,t-1,5),M(e,r-4,4),a=0;a>>8&255,e.pending_buf[e.d_buf+2*e.last_lit+1]=255&n,e.pending_buf[e.l_buf+e.last_lit]=255&t,e.last_lit++,0===n?e.dyn_ltree[2*t]++:(e.matches++,n--,e.dyn_ltree[2*(E[t]+u+1)]++,e.dyn_dtree[2*T(n)]++),e.last_lit===e.lit_bufsize-1},t._tr_align=function(e){M(e,2,3),B(e,g,z),function(e){16===e.bi_valid?(q(e,e.bi_buf),e.bi_buf=0,e.bi_valid=0):8<=e.bi_valid&&(e.pending_buf[e.pending++]=255&e.bi_buf,e.bi_buf>>=8,e.bi_valid-=8)}(e)}},{"../utils/common":41}],53:[function(e,n,t){"use strict";n.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},{}],54:[function(e,n,r){(function(e){!function(e,n){"use strict";if(!e.setImmediate){var t,r,a,i,o=1,s={},l=!1,u=e.document,c=Object.getPrototypeOf&&Object.getPrototypeOf(e);c=c&&c.setTimeout?c:e,t="[object process]"==={}.toString.call(e.process)?function(e){process.nextTick((function(){f(e)}))}:function(){if(e.postMessage&&!e.importScripts){var n=!0,t=e.onmessage;return e.onmessage=function(){n=!1},e.postMessage("","*"),e.onmessage=t,n}}()?(i="setImmediate$"+Math.random()+"$",e.addEventListener?e.addEventListener("message",m,!1):e.attachEvent("onmessage",m),function(n){e.postMessage(i+n,"*")}):e.MessageChannel?((a=new MessageChannel).port1.onmessage=function(e){f(e.data)},function(e){a.port2.postMessage(e)}):u&&"onreadystatechange"in u.createElement("script")?(r=u.documentElement,function(e){var n=u.createElement("script");n.onreadystatechange=function(){f(e),n.onreadystatechange=null,r.removeChild(n),n=null},r.appendChild(n)}):function(e){setTimeout(f,0,e)},c.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var n=new Array(arguments.length-1),r=0;r{"use strict";e.exports=t.p+"6c2b1b2b5bfe2df2c30a.wasm"},878:(e,n,t)=>{"use strict";e.exports=t.p+"ac20e389529269f07a8b.wasm"}},r={};function a(e){var n=r[e];if(void 0!==n)return n.exports;var i=r[e]={id:e,loaded:!1,exports:{}};return t[e](i,i.exports,a),i.loaded=!0,i.exports}a.m=t,a.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return a.d(n,{a:n}),n},a.d=(e,n)=>{for(var t in n)a.o(n,t)&&!a.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},a.f={},a.e=e=>Promise.all(Object.keys(a.f).reduce(((n,t)=>(a.f[t](e,n),n)),[])),a.u=e=>"core.ruffle."+{159:"f679a9cca02e131ea881",339:"67bc37f4e63c43ff9c64"}[e]+".js",a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),a.hmd=e=>((e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set:()=>{throw new Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e),a.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),e={},n="ruffle-selfhosted:",a.l=(t,r,i,o)=>{if(e[t])e[t].push(r);else{var s,l;if(void 0!==i)for(var u=document.getElementsByTagName("script"),c=0;c{s.onerror=s.onload=null,clearTimeout(m);var a=e[t];if(delete e[t],s.parentNode&&s.parentNode.removeChild(s),a&&a.forEach((e=>e(r))),n)return n(r)},m=setTimeout(f.bind(null,void 0,{type:"timeout",target:s}),12e4);s.onerror=f.bind(null,s.onerror),s.onload=f.bind(null,s.onload),l&&document.head.appendChild(s)}},a.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.p="",(()=>{a.b=document.baseURI||self.location.href;var e={179:0};a.f.j=(n,t)=>{var r=a.o(e,n)?e[n]:void 0;if(0!==r)if(r)t.push(r[2]);else{var i=new Promise(((t,a)=>r=e[n]=[t,a]));t.push(r[2]=i);var o=a.p+a.u(n),s=new Error;a.l(o,(t=>{if(a.o(e,n)&&(0!==(r=e[n])&&(e[n]=void 0),r)){var i=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;s.message="Loading chunk "+n+" failed.\n("+i+": "+o+")",s.name="ChunkLoadError",s.type=i,s.request=o,r[1](s)}}),"chunk-"+n,n)}};var n=(n,t)=>{var r,i,[o,s,l]=t,u=0;if(o.some((n=>0!==e[n]))){for(r in s)a.o(s,r)&&(a.m[r]=s[r]);if(l)l(a)}for(n&&n(t);u{"use strict";class e{constructor(e,n,t,r,a){this.major=e,this.minor=n,this.patch=t,this.prIdent=r,this.buildIdent=a}static fromSemver(n){const t=n.split("+"),r=t[0].split("-"),a=r[0].split("."),i=parseInt(a[0],10);let o=0,s=0,l=null,u=null;return void 0!==a[1]&&(o=parseInt(a[1],10)),void 0!==a[2]&&(s=parseInt(a[2],10)),void 0!==r[1]&&(l=r[1].split(".")),void 0!==t[1]&&(u=t[1].split(".")),new e(i,o,s,l,u)}isCompatibleWith(e){return 0!==this.major&&this.major===e.major||0===this.major&&0===e.major&&0!==this.minor&&this.minor===e.minor||0===this.major&&0===e.major&&0===this.minor&&0===e.minor&&0!==this.patch&&this.patch===e.patch}hasPrecedenceOver(e){if(this.major>e.major)return!0;if(this.majore.minor)return!0;if(this.minore.patch)return!0;if(this.patchr)return!0;if(ne.prIdent[t])return!0;if(this.prIdent[t]e.prIdent.length)return!0;if(this.prIdent.lengthr)return!0;if(ne.buildIdent[t])return!0;if(this.buildIdent[t]e.buildIdent.length}return!1}isEqual(e){return this.major===e.major&&this.minor===e.minor&&this.patch===e.patch}isStableOrCompatiblePrerelease(e){return null===e.prIdent||this.major===e.major&&this.minor===e.minor&&this.patch===e.patch}}class n{constructor(e){this.requirements=e}satisfiedBy(e){for(const n of this.requirements){let t=!0;for(const{comparator:r,version:a}of n)t=t&&a.isStableOrCompatiblePrerelease(e),""===r||"="===r?t=t&&a.isEqual(e):">"===r?t=t&&e.hasPrecedenceOver(a):">="===r?t=t&&(e.hasPrecedenceOver(a)||a.isEqual(e)):"<"===r?t=t&&a.hasPrecedenceOver(e):"<="===r?t=t&&(a.hasPrecedenceOver(e)||a.isEqual(e)):"^"===r&&(t=t&&a.isCompatibleWith(e));if(t)return!0}return!1}static fromRequirementString(t){const r=t.split(" ");let a=[];const i=[];for(const n of r)if("||"===n)a.length>0&&(i.push(a),a=[]);else if(n.length>0){const t=/[0-9]/.exec(n);if(t){const r=n.slice(0,t.index).trim(),i=e.fromSemver(n.slice(t.index).trim());a.push({comparator:r,version:i})}}return a.length>0&&i.push(a),new n(i)}}const t=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,5,3,1,0,1,10,14,1,12,0,65,0,65,0,65,0,252,10,0,0,11])),r=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,7,1,5,0,208,112,26,11])),i=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,12,1,10,0,67,0,0,0,0,252,0,26,11])),o=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,8,1,6,0,65,0,192,26,11])),s=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11]));function l(e){const n="function"==typeof Function.prototype.toString?Function.prototype.toString():null;return"string"==typeof n&&n.indexOf("[native code]")>=0&&Function.prototype.toString.call(e).indexOf("[native code]")>=0}function u(){"function"==typeof Array.prototype.reduce&&l(Array.prototype.reduce)||Object.defineProperty(Array.prototype,"reduce",{value(...e){if(0===e.length&&window.Prototype&&window.Prototype.Version&&window.Prototype.Version<"1.6.1")return this.length>1?this:this[0];const n=e[0];if(null===this)throw new TypeError("Array.prototype.reduce called on null or undefined");if("function"!=typeof n)throw new TypeError(`${n} is not a function`);const t=Object(this),r=t.length>>>0;let a,i=0;if(e.length>=2)a=e[1];else{for(;i=r)throw new TypeError("Reduce of empty array with no initial value");a=t[i++]}for(;ie[n]}),"function"!=typeof Reflect.set&&Object.defineProperty(Reflect,"set",{value(e,n,t){e[n]=t}}),"function"!=typeof Reflect.has&&Object.defineProperty(Reflect,"has",{value:(e,n)=>n in e}),"function"!=typeof Reflect.ownKeys&&Object.defineProperty(Reflect,"ownKeys",{value:e=>[...Object.getOwnPropertyNames(e),...Object.getOwnPropertySymbols(e)]})}let c=null,d=!1;try{if(void 0!==document.currentScript&&null!==document.currentScript&&"src"in document.currentScript&&""!==document.currentScript.src){let e=document.currentScript.src;e.endsWith(".js")||e.endsWith("/")||(e+="/"),c=new URL(".",e),d=c.protocol.includes("extension")}}catch(e){console.warn("Unable to get currentScript URL")}function f(e){var n;let t=null!==(n=null==c?void 0:c.href)&&void 0!==n?n:"";return!d&&"publicPath"in e&&null!==e.publicPath&&void 0!==e.publicPath&&(t=e.publicPath),""===t||t.endsWith("/")||(t+="/"),t}let m=null;async function h(e,n,l,c){null===m&&(m=async function(e,n){var l;u();const c=(await Promise.all([t(),s(),i(),o(),r()])).every(Boolean);c||console.log("Some WebAssembly extensions are NOT available, falling back to the vanilla WebAssembly module");try{a.p=f(e)}catch(e){}const{default:d,Ruffle:m}=await(c?a.e(339).then(a.bind(a,339)):a.e(159).then(a.bind(a,159)));let h;const p=c?new URL(a(899),a.b):new URL(a(878),a.b),v=await fetch(p),g="function"==typeof ReadableStream;if(n&&g){const e=(null===(l=null==v?void 0:v.headers)||void 0===l?void 0:l.get("content-length"))||"";let t=0;const r=parseInt(e);h=new Response(new ReadableStream({async start(e){var a;const i=null===(a=v.body)||void 0===a?void 0:a.getReader();if(!i)throw"Response had no body";for(n(t,r);;){const{done:a,value:o}=await i.read();if(a)break;(null==o?void 0:o.byteLength)&&(t+=null==o?void 0:o.byteLength),e.enqueue(o),n(t,r)}e.close()}}),v)}else h=v;return await d(h),m}(l,c));return new(await m)(e,n,l)}class p{constructor(e){this.value=e}valueOf(){return this.value}}class v extends p{constructor(e="???"){super(e)}toString(e){return`{${this.value}}`}}class g extends p{constructor(e,n={}){super(e),this.opts=n}toString(e){try{return e.memoizeIntlObject(Intl.NumberFormat,this.opts).format(this.value)}catch(n){return e.reportError(n),this.value.toString(10)}}}class b extends p{constructor(e,n={}){super(e),this.opts=n}toString(e){try{return e.memoizeIntlObject(Intl.DateTimeFormat,this.opts).format(this.value)}catch(n){return e.reportError(n),new Date(this.value).toISOString()}}}const w=100,k="\u2068",y="\u2069";function x(e,n,t){if(t===n)return!0;if(t instanceof g&&n instanceof g&&t.value===n.value)return!0;if(n instanceof g&&"string"==typeof t){if(t===e.memoizeIntlObject(Intl.PluralRules,n.opts).select(n.value))return!0}return!1}function R(e,n,t){return n[t]?j(e,n[t].value):(e.reportError(new RangeError("No default")),new v)}function _(e,n){const t=[],r=Object.create(null);for(const a of n)"narg"===a.type?r[a.name]=z(e,a.value):t.push(z(e,a));return{positional:t,named:r}}function z(e,n){switch(n.type){case"str":return n.value;case"num":return new g(n.value,{minimumFractionDigits:n.precision});case"var":return function(e,{name:n}){let t;if(e.params){if(!Object.prototype.hasOwnProperty.call(e.params,n))return new v(`$${n}`);t=e.params[n]}else{if(!e.args||!Object.prototype.hasOwnProperty.call(e.args,n))return e.reportError(new ReferenceError(`Unknown variable: $${n}`)),new v(`$${n}`);t=e.args[n]}if(t instanceof p)return t;switch(typeof t){case"string":return t;case"number":return new g(t);case"object":if(t instanceof Date)return new b(t.getTime());default:return e.reportError(new TypeError(`Variable type not supported: $${n}, ${typeof t}`)),new v(`$${n}`)}}(e,n);case"mesg":return function(e,{name:n,attr:t}){const r=e.bundle._messages.get(n);if(!r)return e.reportError(new ReferenceError(`Unknown message: ${n}`)),new v(n);if(t){const a=r.attributes[t];return a?j(e,a):(e.reportError(new ReferenceError(`Unknown attribute: ${t}`)),new v(`${n}.${t}`))}if(r.value)return j(e,r.value);return e.reportError(new ReferenceError(`No value: ${n}`)),new v(n)}(e,n);case"term":return function(e,{name:n,attr:t,args:r}){const a=`-${n}`,i=e.bundle._terms.get(a);if(!i)return e.reportError(new ReferenceError(`Unknown term: ${a}`)),new v(a);if(t){const n=i.attributes[t];if(n){e.params=_(e,r).named;const t=j(e,n);return e.params=null,t}return e.reportError(new ReferenceError(`Unknown attribute: ${t}`)),new v(`${a}.${t}`)}e.params=_(e,r).named;const o=j(e,i.value);return e.params=null,o}(e,n);case"func":return function(e,{name:n,args:t}){let r=e.bundle._functions[n];if(!r)return e.reportError(new ReferenceError(`Unknown function: ${n}()`)),new v(`${n}()`);if("function"!=typeof r)return e.reportError(new TypeError(`Function ${n}() is not callable`)),new v(`${n}()`);try{let n=_(e,t);return r(n.positional,n.named)}catch(t){return e.reportError(t),new v(`${n}()`)}}(e,n);case"select":return function(e,{selector:n,variants:t,star:r}){let a=z(e,n);if(a instanceof v)return R(e,t,r);for(const n of t){if(x(e,a,z(e,n.key)))return j(e,n.value)}return R(e,t,r)}(e,n);default:return new v}}function S(e,n){if(e.dirty.has(n))return e.reportError(new RangeError("Cyclic reference")),new v;e.dirty.add(n);const t=[],r=e.bundle._useIsolating&&n.length>1;for(const a of n)if("string"!=typeof a){if(e.placeables++,e.placeables>w)throw e.dirty.delete(n),new RangeError(`Too many placeables expanded: ${e.placeables}, max allowed is ${w}`);r&&t.push(k),t.push(z(e,a).toString(e)),r&&t.push(y)}else t.push(e.bundle._transform(a));return e.dirty.delete(n),t.join("")}function j(e,n){return"string"==typeof n?e.bundle._transform(n):S(e,n)}class E{constructor(e,n,t){this.dirty=new WeakSet,this.params=null,this.placeables=0,this.bundle=e,this.errors=n,this.args=t}reportError(e){if(!(this.errors&&e instanceof Error))throw e;this.errors.push(e)}memoizeIntlObject(e,n){let t=this.bundle._intls.get(e);t||(t={},this.bundle._intls.set(e,t));let r=JSON.stringify(n);return t[r]||(t[r]=new e(this.bundle.locales,n)),t[r]}}function C(e,n){const t=Object.create(null);for(const[r,a]of Object.entries(e))n.includes(r)&&(t[r]=a.valueOf());return t}const A=["unitDisplay","currencyDisplay","useGrouping","minimumIntegerDigits","minimumFractionDigits","maximumFractionDigits","minimumSignificantDigits","maximumSignificantDigits"];function I(e,n){let t=e[0];if(t instanceof v)return new v(`NUMBER(${t.valueOf()})`);if(t instanceof g)return new g(t.valueOf(),{...t.opts,...C(n,A)});if(t instanceof b)return new g(t.valueOf(),{...C(n,A)});throw new TypeError("Invalid argument to NUMBER")}const F=["dateStyle","timeStyle","fractionalSecondDigits","dayPeriod","hour12","weekday","era","year","month","day","hour","minute","second","timeZoneName"];function O(e,n){let t=e[0];if(t instanceof v)return new v(`DATETIME(${t.valueOf()})`);if(t instanceof b)return new b(t.valueOf(),{...t.opts,...C(n,F)});if(t instanceof g)return new b(t.valueOf(),{...C(n,F)});throw new TypeError("Invalid argument to DATETIME")}const D=new Map;class P{constructor(e,{functions:n,useIsolating:t=!0,transform:r=(e=>e)}={}){this._terms=new Map,this._messages=new Map,this.locales=Array.isArray(e)?e:[e],this._functions={NUMBER:I,DATETIME:O,...n},this._useIsolating=t,this._transform=r,this._intls=function(e){const n=Array.isArray(e)?e.join(" "):e;let t=D.get(n);return void 0===t&&(t=new Map,D.set(n,t)),t}(e)}hasMessage(e){return this._messages.has(e)}getMessage(e){return this._messages.get(e)}addResource(e,{allowOverrides:n=!1}={}){const t=[];for(let r=0;r\s*/y,re=/\s*:\s*/y,ae=/\s*,?\s*/y,ie=/\s+/y;class oe{constructor(e){this.body=[],T.lastIndex=0;let n=0;for(;;){let t=T.exec(e);if(null===t)break;n=T.lastIndex;try{this.body.push(s(t[1]))}catch(e){if(e instanceof SyntaxError)continue;throw e}}function t(t){return t.lastIndex=n,t.test(e)}function r(t,r){if(e[n]===t)return n++,!0;if(r)throw new r(`Expected ${t}`);return!1}function a(e,r){if(t(e))return n=e.lastIndex,!0;if(r)throw new r(`Expected ${e.toString()}`);return!1}function i(t){t.lastIndex=n;let r=t.exec(e);if(null===r)throw new SyntaxError(`Expected ${t.toString()}`);return n=t.lastIndex,r}function o(e){return i(e)[1]}function s(e){let n=l(),r=function(){let e=Object.create(null);for(;t(q);){let n=o(q),t=l();if(null===t)throw new SyntaxError("Expected attribute value");e[n]=t}return e}();if(null===n&&0===Object.keys(r).length)throw new SyntaxError("Expected message value or attributes");return{id:e,value:n,attributes:r}}function l(){let r;if(t(N)&&(r=o(N)),"{"===e[n]||"}"===e[n])return u(r?[r]:[],1/0);let a=g();return a?r?u([r,a],a.length):(a.value=b(a.value,J),u([a],a.length)):r?b(r,V):null}function u(r=[],a){for(;;){if(t(N)){r.push(o(N));continue}if("{"===e[n]){r.push(c());continue}if("}"===e[n])throw new SyntaxError("Unbalanced closing brace");let i=g();if(!i)break;r.push(i),a=Math.min(a,i.length)}let i=r.length-1,s=r[i];"string"==typeof s&&(r[i]=b(s,V));let l=[];for(let e of r)e instanceof se&&(e=e.value.slice(0,e.value.length-a)),e&&l.push(e);return l}function c(){a(Y,SyntaxError);let e=d();if(a(X))return e;if(a(te)){let n=function(){let e,n=[],a=0;for(;t(M);){r("*")&&(e=a);let t=m(),i=l();if(null===i)throw new SyntaxError("Expected variant value");n[a++]={key:t,value:i}}if(0===a)return null;if(void 0===e)throw new SyntaxError("Expected default variant");return{variants:n,star:e}}();return a(X,SyntaxError),{type:"select",selector:e,...n}}throw new SyntaxError("Unclosed placeable")}function d(){if("{"===e[n])return c();if(t(L)){let[,t,r,o=null]=i(L);if("$"===t)return{type:"var",name:r};if(a(ne)){let i=function(){let t=[];for(;;){switch(e[n]){case")":return n++,t;case void 0:throw new SyntaxError("Unclosed argument list")}t.push(f()),a(ae)}}();if("-"===t)return{type:"term",name:r,attr:o,args:i};if($.test(r))return{type:"func",name:r,args:i};throw new SyntaxError("Function names must be all upper-case")}return"-"===t?{type:"term",name:r,attr:o,args:[]}:{type:"mesg",name:r,attr:o}}return h()}function f(){let e=d();return"mesg"!==e.type?e:a(re)?{type:"narg",name:e.name,value:h()}:e}function m(){let e;return a(Q,SyntaxError),e=t(B)?p():{type:"str",value:o(W)},a(ee,SyntaxError),e}function h(){if(t(B))return p();if('"'===e[n])return function(){r('"',SyntaxError);let t="";for(;;){if(t+=o(U),"\\"!==e[n]){if(r('"'))return{type:"str",value:t};throw new SyntaxError("Unclosed string literal")}t+=v()}}();throw new SyntaxError("Invalid expression")}function p(){let[,e,n=""]=i(B),t=n.length;return{type:"num",value:parseFloat(e),precision:t}}function v(){if(t(Z))return o(Z);if(t(H)){let[,e,n]=i(H),t=parseInt(e||n,16);return t<=55295||57344<=t?String.fromCodePoint(t):"\ufffd"}throw new SyntaxError("Unknown escape sequence")}function g(){let t=n;switch(a(ie),e[n]){case".":case"[":case"*":case"}":case void 0:return!1;case"{":return w(e.slice(t,n))}return" "===e[n-1]&&w(e.slice(t,n))}function b(e,n){return e.replace(n,"")}function w(e){let n=e.replace(K,"\n"),t=G.exec(e)[1].length;return new se(n,t)}}}class se{constructor(e,n){this.value=e,this.length=n}}const le=new RegExp("^([a-z]{2,3}|\\*)(?:-([a-z]{4}|\\*))?(?:-([a-z]{2}|\\*))?(?:-(([0-9][a-z0-9]{3}|[a-z0-9]{5,8})|\\*))?$","i");class ue{constructor(e){const n=le.exec(e.replace(/_/g,"-"));if(!n)return void(this.isWellFormed=!1);let[,t,r,a,i]=n;t&&(this.language=t.toLowerCase()),r&&(this.script=r[0].toUpperCase()+r.slice(1)),a&&(this.region=a.toUpperCase()),this.variant=i,this.isWellFormed=!0}isEqual(e){return this.language===e.language&&this.script===e.script&&this.region===e.region&&this.variant===e.variant}matches(e,n=!1,t=!1){return(this.language===e.language||n&&void 0===this.language||t&&void 0===e.language)&&(this.script===e.script||n&&void 0===this.script||t&&void 0===e.script)&&(this.region===e.region||n&&void 0===this.region||t&&void 0===e.region)&&(this.variant===e.variant||n&&void 0===this.variant||t&&void 0===e.variant)}toString(){return[this.language,this.script,this.region,this.variant].filter((e=>void 0!==e)).join("-")}clearVariants(){this.variant=void 0}clearRegion(){this.region=void 0}addLikelySubtags(){const e=function(e){if(Object.prototype.hasOwnProperty.call(ce,e))return new ue(ce[e]);const n=new ue(e);if(n.language&&de.includes(n.language))return n.region=n.language.toUpperCase(),n;return null}(this.toString().toLowerCase());return!!e&&(this.language=e.language,this.script=e.script,this.region=e.region,this.variant=e.variant,!0)}}const ce={ar:"ar-arab-eg","az-arab":"az-arab-ir","az-ir":"az-arab-ir",be:"be-cyrl-by",da:"da-latn-dk",el:"el-grek-gr",en:"en-latn-us",fa:"fa-arab-ir",ja:"ja-jpan-jp",ko:"ko-kore-kr",pt:"pt-latn-br",sr:"sr-cyrl-rs","sr-ru":"sr-latn-ru",sv:"sv-latn-se",ta:"ta-taml-in",uk:"uk-cyrl-ua",zh:"zh-hans-cn","zh-hant":"zh-hant-tw","zh-hk":"zh-hant-hk","zh-mo":"zh-hant-mo","zh-tw":"zh-hant-tw","zh-gb":"zh-hant-gb","zh-us":"zh-hant-us"},de=["az","bg","cs","de","es","fi","fr","hu","it","lt","lv","nl","pl","ro","ru"];function fe(e,n,{strategy:t="filtering",defaultLocale:r}={}){const a=function(e,n,t){const r=new Set,a=new Map;for(let e of n)new ue(e).isWellFormed&&a.set(e,new ue(e));e:for(const n of e){const e=n.toLowerCase(),i=new ue(e);if(void 0!==i.language){for(const n of a.keys())if(e===n.toLowerCase()){if(r.add(n),a.delete(n),"lookup"===t)return Array.from(r);if("filtering"===t)continue;continue e}for(const[e,n]of a.entries())if(n.matches(i,!0,!1)){if(r.add(e),a.delete(e),"lookup"===t)return Array.from(r);if("filtering"===t)continue;continue e}if(i.addLikelySubtags())for(const[e,n]of a.entries())if(n.matches(i,!0,!1)){if(r.add(e),a.delete(e),"lookup"===t)return Array.from(r);if("filtering"===t)continue;continue e}i.clearVariants();for(const[e,n]of a.entries())if(n.matches(i,!0,!0)){if(r.add(e),a.delete(e),"lookup"===t)return Array.from(r);if("filtering"===t)continue;continue e}if(i.clearRegion(),i.addLikelySubtags())for(const[e,n]of a.entries())if(n.matches(i,!0,!1)){if(r.add(e),a.delete(e),"lookup"===t)return Array.from(r);if("filtering"===t)continue;continue e}i.clearRegion();for(const[e,n]of a.entries())if(n.matches(i,!0,!0)){if(r.add(e),a.delete(e),"lookup"===t)return Array.from(r);if("filtering"===t)continue;continue e}}}return Array.from(r)}(Array.from(null!=e?e:[]).map(String),Array.from(null!=n?n:[]).map(String),t);if("lookup"===t){if(void 0===r)throw new Error("defaultLocale cannot be undefined for strategy `lookup`");0===a.length&&a.push(r)}else r&&!a.includes(r)&&a.push(r);return a}const me={"ar-SA":{"context_menu.ftl":"context-menu-download-swf = \u062a\u062d\u0645\u064a\u0644 .swf\ncontext-menu-copy-debug-info = \u0646\u0633\u062e \u0645\u0639\u0644\u0648\u0645\u0627\u062a \u0627\u0644\u062a\u0635\u062d\u064a\u062d\ncontext-menu-open-save-manager = \u0641\u062a\u062d \u0645\u062f\u064a\u0631 \u0627\u0644\u062d\u0641\u0638\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] \u062d\u0648\u0644 \u0645\u0644\u062d\u0642 \u0631\u0641\u0644 ({ $version })\n *[other] \u062d\u0648\u0644 \u0631\u0641\u0644 ({ $version })\n }\ncontext-menu-hide = \u0625\u062e\u0641\u0627\u0621 \u0647\u0630\u0647 \u0627\u0644\u0642\u0627\u0626\u0645\u0629\ncontext-menu-exit-fullscreen = \u0627\u0644\u062e\u0631\u0648\u062c \u0645\u0646 \u0648\u0636\u0639\u064a\u0629 \u0627\u0644\u0634\u0627\u0634\u0629 \u0627\u0644\u0643\u0627\u0645\u0644\u0629\ncontext-menu-enter-fullscreen = \u062a\u0641\u0639\u064a\u0644 \u0648\u0636\u0639\u064a\u0629 \u0627\u0644\u0634\u0627\u0634\u0629 \u0627\u0644\u0643\u0627\u0645\u0644\u0629\ncontext-menu-volume-controls = \u0627\u0644\u062a\u062d\u0643\u0645 \u0628\u0627\u0644\u0635\u0648\u062a\n","messages.ftl":'message-cant-embed =\n \u0644\u0645 \u062a\u0643\u0646 \u0631\u0641\u0644 \u0642\u0627\u062f\u0631\u0629 \u0639\u0644\u0649 \u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u0641\u0644\u0627\u0634 \u0627\u0644\u0645\u0636\u0645\u0646\u0629 \u0641\u064a \u0647\u0630\u0647 \u0627\u0644\u0635\u0641\u062d\u0629.\n \u064a\u0645\u0643\u0646\u0643 \u0645\u062d\u0627\u0648\u0644\u0629 \u0641\u062a\u062d \u0627\u0644\u0645\u0644\u0641 \u0641\u064a \u0639\u0644\u0627\u0645\u0629 \u062a\u0628\u0648\u064a\u0628 \u0645\u0646\u0641\u0635\u0644\u0629\u060c \u0644\u062a\u062c\u0627\u0648\u0632 \u0647\u0630\u0647 \u0627\u0644\u0645\u0634\u0643\u0644\u0629.\npanic-title = \u0644\u0642\u062f \u062d\u062f\u062b \u062e\u0637\u0623 \u0645\u0627 :(\nmore-info = \u0645\u0639\u0644\u0648\u0645\u0627\u062a \u0623\u0643\u062b\u0631\nrun-anyway = \u0627\u0644\u062a\u0634\u063a\u064a\u0644 \u0639\u0644\u0649 \u0623\u064a \u062d\u0627\u0644\ncontinue = \u0627\u0644\u0627\u0633\u062a\u0645\u0631\u0627\u0631\nreport-bug = \u0625\u0628\u0644\u0627\u063a \u0639\u0646 \u062e\u0644\u0644\nupdate-ruffle = \u062a\u062d\u062f\u064a\u062b \u0631\u0641\u0644\nruffle-demo = \u0648\u064a\u0628 \u0627\u0644\u062a\u062c\u0631\u064a\u0628\u064a\nruffle-desktop = \u0628\u0631\u0646\u0627\u0645\u062c \u0633\u0637\u062d \u0627\u0644\u0645\u0643\u062a\u0628\nruffle-wiki = \u0639\u0631\u0636 \u0631\u0641\u0644 \u0648\u064a\u0643\u064a\nenable-hardware-acceleration = \u064a\u0628\u062f\u0648 \u0623\u0646 \u062a\u0633\u0627\u0631\u0639 \u0627\u0644\u0623\u062c\u0647\u0632\u0629 \u063a\u064a\u0631 \u0645\u0641\u0639\u0644. \u0628\u064a\u0646\u0645\u0627 \u0642\u062f \u064a\u0639\u0645\u0644 \u0627\u0644\u0631\u0648\u0641\u0644\u060c \u0642\u062f \u064a\u0643\u0648\u0646 \u0628\u0637\u064a\u0626\u0627\u064b \u0628\u0634\u0643\u0644 \u063a\u064a\u0631 \u0645\u0639\u0642\u0648\u0644. \u064a\u0645\u0643\u0646\u0643 \u0645\u0639\u0631\u0641\u0629 \u0643\u064a\u0641\u064a\u0629 \u062a\u0645\u0643\u064a\u0646 \u062a\u0633\u0627\u0631\u0639 \u0627\u0644\u0623\u062c\u0647\u0632\u0629 \u0645\u0646 \u062e\u0644\u0627\u0644 \u0645\u062a\u0627\u0628\u0639\u0629 \u0647\u0630\u0627 \u0627\u0644\u0631\u0627\u0628\u0637.\nview-error-details = \u0639\u0631\u0636 \u062a\u0641\u0627\u0635\u064a\u0644 \u0627\u0644\u062e\u0637\u0623\nopen-in-new-tab = \u0641\u062a\u062d \u0641\u064a \u0639\u0644\u0627\u0645\u0629 \u062a\u0628\u0648\u064a\u0628 \u062c\u062f\u064a\u062f\u0629\nclick-to-unmute = \u0627\u0646\u0642\u0631 \u0644\u0625\u0644\u063a\u0627\u0621 \u0627\u0644\u0643\u062a\u0645\nerror-file-protocol =\n \u064a\u0628\u062f\u0648 \u0623\u0646\u0643 \u062a\u0642\u0648\u0645 \u0628\u062a\u0634\u063a\u064a\u0644 \u0631\u0641\u0644 \u0639\u0644\u0649 \u0628\u0631\u0648\u062a\u0648\u0643\u0648\u0644 "\u0627\u0644\u0645\u0644\u0641:".\n \u0647\u0630\u0627 \u0644\u0646 \u064a\u0639\u0645\u0644 \u0644\u0623\u0646 \u0627\u0644\u0645\u062a\u0635\u0641\u062d\u0627\u062a \u062a\u0645\u0646\u0639 \u0627\u0644\u0639\u062f\u064a\u062f \u0645\u0646 \u0627\u0644\u0645\u064a\u0632\u0627\u062a \u0645\u0646 \u0627\u0644\u0639\u0645\u0644 \u0644\u0623\u0633\u0628\u0627\u0628 \u0623\u0645\u0646\u064a\u0629.\n \u0628\u062f\u0644\u0627\u064b \u0645\u0646 \u0630\u0644\u0643\u060c \u0646\u062f\u0639\u0648\u0643 \u0625\u0644\u0649 \u0625\u0639\u062f\u0627\u062f \u062e\u0627\u062f\u0645 \u0645\u062d\u0644\u064a \u0623\u0648 \u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0639\u0631\u0636 \u0627\u0644\u0648\u064a\u0628 \u0623\u0648 \u062a\u0637\u0628\u064a\u0642 \u0633\u0637\u062d \u0627\u0644\u0645\u0643\u062a\u0628.\nerror-javascript-config =\n \u062a\u0639\u0631\u0636 \u0631\u0641\u0644 \u0625\u0644\u0649 \u0645\u0634\u0643\u0644\u0629 \u0631\u0626\u064a\u0633\u064a\u0629 \u0628\u0633\u0628\u0628 \u0627\u0644\u0625\u0639\u062f\u0627\u062f\u0627\u062a \u0627\u0644\u062e\u0627\u0637\u0626\u0629 \u0644\u0644\u062c\u0627\u0641\u0627 \u0633\u0643\u0631\u064a\u0628\u062a.\n \u0625\u0630\u0627 \u0643\u0646\u062a \u0645\u0633\u0624\u0648\u0644 \u0627\u0644\u062e\u0627\u062f\u0645\u060c \u0646\u062d\u0646 \u0646\u062f\u0639\u0648\u0643 \u0625\u0644\u0649 \u0627\u0644\u062a\u062d\u0642\u0642 \u0645\u0646 \u062a\u0641\u0627\u0635\u064a\u0644 \u0627\u0644\u062e\u0637\u0623 \u0644\u0645\u0639\u0631\u0641\u0629 \u0633\u0628\u0628 \u0627\u0644\u0645\u0634\u0643\u0644\u0629.\n \u064a\u0645\u0643\u0646\u0643 \u0623\u064a\u0636\u0627 \u0627\u0644\u0631\u062c\u0648\u0639 \u0625\u0644\u0649 \u0631\u0641\u0644 \u0648\u064a\u0643\u064a \u0644\u0644\u062d\u0635\u0648\u0644 \u0639\u0644\u0649 \u0627\u0644\u0645\u0633\u0627\u0639\u062f\u0629.\nerror-wasm-not-found =\n \u0641\u0634\u0644 \u0631\u0641\u0644 \u0641\u064a \u062a\u062d\u0645\u064a\u0644 \u0645\u0643\u0648\u0646 \u0627\u0644\u0645\u0644\u0641 ".wasm" \u0627\u0644\u0645\u0637\u0644\u0648\u0628.\n \u0625\u0630\u0627 \u0643\u0646\u062a \u0645\u0633\u0624\u0648\u0644 \u0627\u0644\u062e\u0627\u062f\u0645\u060c \u0627\u0644\u0631\u062c\u0627\u0621 \u0627\u0644\u062a\u0623\u0643\u062f \u0645\u0646 \u0623\u0646 \u0627\u0644\u0645\u0644\u0641 \u0642\u062f \u062a\u0645 \u062a\u062d\u0645\u064a\u0644\u0647 \u0628\u0634\u0643\u0644 \u0635\u062d\u064a\u062d.\n \u0625\u0630\u0627 \u0627\u0633\u062a\u0645\u0631\u062a \u0627\u0644\u0645\u0634\u0643\u0644\u0629\u060c \u0642\u062f \u062a\u062d\u062a\u0627\u062c \u0625\u0644\u0649 \u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0625\u0639\u062f\u0627\u062f\u0627\u062a "\u0627\u0644\u0645\u0633\u0627\u0631 \u0627\u0644\u0639\u0627\u0645": \u0627\u0644\u0631\u062c\u0627\u0621 \u0645\u0631\u0627\u062c\u0639\u0629 \u0631\u0641\u0644 \u0648\u064a\u0643\u064a \u0644\u0644\u062d\u0635\u0648\u0644 \u0639\u0644\u0649 \u0627\u0644\u0645\u0633\u0627\u0639\u062f\u0629.\nerror-wasm-mime-type =\n \u0648\u0627\u062c\u0647\u062a \u0631\u0641\u0644 \u0645\u0634\u0643\u0644\u0629 \u0631\u0626\u064a\u0633\u064a\u0629 \u0623\u062b\u0646\u0627\u0621 \u0645\u062d\u0627\u0648\u0644\u0629 \u0627\u0644\u062a\u0647\u064a\u0626\u0629.\n \u062e\u0627\u062f\u0645 \u0627\u0644\u0648\u064a\u0628 \u0647\u0630\u0627 \u0644\u0627 \u064a\u062e\u062f\u0645 \u0645\u0644\u0641\u0627\u062a ". wasm" \u0645\u0639 \u0646\u0648\u0639 MIME \u0627\u0644\u0635\u062d\u064a\u062d.\n \u0625\u0630\u0627 \u0643\u0646\u062a \u0645\u0633\u0624\u0648\u0644 \u0627\u0644\u062e\u0627\u062f\u0645\u060c \u064a\u0631\u062c\u0649 \u0645\u0631\u0627\u062c\u0639\u0629 \u0631\u0641\u0644 \u0648\u064a\u0643\u064a \u0644\u0644\u062d\u0635\u0648\u0644 \u0639\u0644\u0649 \u0627\u0644\u0645\u0633\u0627\u0639\u062f\u0629.\nerror-swf-fetch =\n \u0641\u0634\u0644 \u0631\u0641\u0644 \u0641\u064a \u062a\u062d\u0645\u064a\u0644 \u0645\u0644\u0641 \u0641\u0644\u0627\u0634 SWF.\n \u0627\u0644\u0633\u0628\u0628 \u0627\u0644\u0623\u0643\u062b\u0631 \u0627\u062d\u062a\u0645\u0627\u0644\u0627 \u0647\u0648 \u0623\u0646 \u0627\u0644\u0645\u0644\u0641 \u0644\u0645 \u064a\u0639\u062f \u0645\u0648\u062c\u0648\u062f\u0627\u060c \u0644\u0630\u0644\u0643 \u0644\u0627 \u064a\u0648\u062c\u062f \u0634\u064a\u0621 \u0644\u064a\u062d\u0645\u0644\u0647 \u0631\u0641\u0644.\n \u062d\u0627\u0648\u0644 \u0627\u0644\u0627\u062a\u0635\u0627\u0644 \u0628\u0645\u0633\u0624\u0648\u0644 \u0627\u0644\u0645\u0648\u0642\u0639 \u0644\u0644\u062d\u0635\u0648\u0644 \u0639\u0644\u0649 \u0627\u0644\u0645\u0633\u0627\u0639\u062f\u0629.\nerror-swf-cors =\n \u0641\u0634\u0644 \u0627\u0644\u0631\u0648\u0641\u0644 \u0641\u064a \u062a\u062d\u0645\u064a\u0644 \u0645\u0644\u0641 \u0641\u0644\u0627\u0634 SWF.\n \u0645\u0646 \u0627\u0644\u0645\u062d\u062a\u0645\u0644 \u0623\u0646 \u062a\u0645 \u062d\u0638\u0631 \u0627\u0644\u0648\u0635\u0648\u0644 \u0625\u0644\u0649 \u0627\u0644\u0645\u0646\u0627\u0644 \u0628\u0648\u0627\u0633\u0637\u0629 \u0633\u064a\u0627\u0633\u0629 CORS.\n \u0625\u0630\u0627 \u0643\u0646\u062a \u0645\u0633\u0624\u0648\u0644 \u0627\u0644\u062e\u0627\u062f\u0645\u060c \u064a\u0631\u062c\u0649 \u0645\u0631\u0627\u062c\u0639\u0629 \u0631\u0641\u0644 \u0648\u064a\u0643\u064a \u0644\u0644\u062d\u0635\u0648\u0644 \u0639\u0644\u0649 \u0627\u0644\u0645\u0633\u0627\u0639\u062f\u0629.\nerror-wasm-cors =\n \u0641\u0634\u0644 \u0631\u0641\u0644 \u0641\u064a \u062a\u062d\u0645\u064a\u0644 \u0645\u0643\u0648\u0646 \u0645\u0644\u0641 ".wasm" \u0627\u0644\u0645\u0637\u0644\u0648\u0628.\n \u0645\u0646 \u0627\u0644\u0645\u062d\u062a\u0645\u0644 \u0623\u0646 \u062a\u0645 \u062d\u0638\u0631 \u0627\u0644\u0648\u0635\u0648\u0644 \u0625\u0644\u0649 \u0627\u0644\u0645\u0646\u0627\u0644 \u0628\u0648\u0627\u0633\u0637\u0629 \u0633\u064a\u0627\u0633\u0629 CORS.\n \u0625\u0630\u0627 \u0643\u0646\u062a \u0645\u0633\u0624\u0648\u0644 \u0627\u0644\u062e\u0627\u062f\u0645\u060c \u064a\u0631\u062c\u0649 \u0645\u0631\u0627\u062c\u0639\u0629 \u0631\u0641\u0644 \u0648\u064a\u0643\u064a \u0644\u0644\u062d\u0635\u0648\u0644 \u0639\u0644\u0649 \u0627\u0644\u0645\u0633\u0627\u0639\u062f\u0629.\nerror-wasm-invalid =\n \u0648\u0627\u062c\u0647\u062a \u0631\u0641\u0644 \u0645\u0634\u0643\u0644\u0629 \u0631\u0626\u064a\u0633\u064a\u0629 \u0623\u062b\u0646\u0627\u0621 \u0645\u062d\u0627\u0648\u0644\u0629 \u0627\u0644\u062a\u0647\u064a\u0626\u0629.\n \u062e\u0627\u062f\u0645 \u0627\u0644\u0648\u064a\u0628 \u0647\u0630\u0627 \u0644\u0627 \u064a\u062e\u062f\u0645 \u0645\u0644\u0641\u0627\u062a ". wasm" \u0645\u0639 \u0646\u0648\u0639 MIME \u0627\u0644\u0635\u062d\u064a\u062d.\n \u0625\u0630\u0627 \u0643\u0646\u062a \u0645\u0633\u0624\u0648\u0644 \u0627\u0644\u062e\u0627\u062f\u0645\u060c \u064a\u0631\u062c\u0649 \u0645\u0631\u0627\u062c\u0639\u0629 \u0631\u0641\u0644 \u0648\u064a\u0643\u064a \u0644\u0644\u062d\u0635\u0648\u0644 \u0639\u0644\u0649 \u0627\u0644\u0645\u0633\u0627\u0639\u062f\u0629.\nerror-wasm-download =\n \u0648\u0627\u062c\u0647\u062a \u0631\u0641\u0644 \u0645\u0634\u0643\u0644\u0629 \u0631\u0626\u064a\u0633\u064a\u0629 \u0623\u062b\u0646\u0627\u0621 \u0645\u062d\u0627\u0648\u0644\u062a\u0647\u0627 \u0627\u0644\u062a\u0647\u064a\u0626\u0629.\n \u0647\u0630\u0627 \u064a\u0645\u0643\u0646 \u0623\u0646 \u064a\u062d\u0644 \u0646\u0641\u0633\u0647 \u0641\u064a \u0643\u062b\u064a\u0631 \u0645\u0646 \u0627\u0644\u0623\u062d\u064a\u0627\u0646\u060c \u0644\u0630\u0644\u0643 \u064a\u0645\u0643\u0646\u0643 \u0645\u062d\u0627\u0648\u0644\u0629 \u0625\u0639\u0627\u062f\u0629 \u062a\u062d\u0645\u064a\u0644 \u0627\u0644\u0635\u0641\u062d\u0629.\n \u062e\u0644\u0627\u0641 \u0630\u0644\u0643\u060c \u064a\u0631\u062c\u0649 \u0627\u0644\u0627\u062a\u0635\u0627\u0644 \u0628\u0645\u062f\u064a\u0631 \u0627\u0644\u0645\u0648\u0642\u0639.\nerror-wasm-disabled-on-edge =\n \u0641\u0634\u0644 \u0631\u0641\u0644 \u0641\u064a \u062a\u062d\u0645\u064a\u0644 \u0645\u0643\u0648\u0646 \u0627\u0644\u0645\u0644\u0641 ".wasm" \u0627\u0644\u0645\u0637\u0644\u0648\u0628.\n \u0644\u0625\u0635\u0644\u0627\u062d \u0647\u0630\u0647 \u0627\u0644\u0645\u0634\u0643\u0644\u0629\u060c \u062d\u0627\u0648\u0644 \u0641\u062a\u062d \u0625\u0639\u062f\u0627\u062f\u0627\u062a \u0627\u0644\u0645\u062a\u0635\u0641\u062d \u0627\u0644\u062e\u0627\u0635 \u0628\u0643\u060c \u0627\u0646\u0642\u0631 \u0641\u0648\u0642 "\u0627\u0644\u062e\u0635\u0648\u0635\u064a\u0629\u060c \u0627\u0644\u0628\u062d\u062b\u060c \u0627\u0644\u062e\u062f\u0645\u0627\u062a"\u060c \u0648\u0627\u0644\u062a\u0645\u0631\u064a\u0631 \u0644\u0623\u0633\u0641\u0644\u060c \u0648\u0625\u064a\u0642\u0627\u0641 "\u062a\u0639\u0632\u064a\u0632 \u0623\u0645\u0627\u0646\u0643 \u0639\u0644\u0649 \u0627\u0644\u0648\u064a\u0628".\n \u0647\u0630\u0627 \u0633\u064a\u0633\u0645\u062d \u0644\u0644\u0645\u062a\u0635\u0641\u062d \u0627\u0644\u062e\u0627\u0635 \u0628\u0643 \u0628\u062a\u062d\u0645\u064a\u0644 \u0627\u0644\u0645\u0644\u0641\u0627\u062a ".wasm" \u0627\u0644\u0645\u0637\u0644\u0648\u0628\u0629.\n \u0625\u0630\u0627 \u0627\u0633\u062a\u0645\u0631\u062a \u0627\u0644\u0645\u0634\u0643\u0644\u0629\u060c \u0642\u062f \u062a\u062d\u062a\u0627\u062c \u0625\u0644\u0649 \u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0645\u062a\u0635\u0641\u062d \u0623\u062e\u0631.\nerror-javascript-conflict =\n \u0648\u0627\u062c\u0647\u062a \u0631\u0641\u0644 \u0645\u0634\u0643\u0644\u0629 \u0631\u0626\u064a\u0633\u064a\u0629 \u0623\u062b\u0646\u0627\u0621 \u0645\u062d\u0627\u0648\u0644\u0629 \u0627\u0644\u062a\u0647\u064a\u0626\u0629.\n \u064a\u0628\u062f\u0648 \u0623\u0646 \u0647\u0630\u0647 \u0627\u0644\u0635\u0641\u062d\u0629 \u062a\u0633\u062a\u062e\u062f\u0645 \u0643\u0648\u062f \u062c\u0627\u0641\u0627 \u0633\u0643\u0631\u064a\u0628\u062a \u0627\u0644\u0630\u064a \u064a\u062a\u0639\u0627\u0631\u0636 \u0645\u0639 \u0631\u0641\u0644.\n \u0625\u0630\u0627 \u0643\u0646\u062a \u0645\u0633\u0624\u0648\u0644 \u0627\u0644\u062e\u0627\u062f\u0645\u060c \u0641\u0625\u0646\u0646\u0627 \u0646\u062f\u0639\u0648\u0643 \u0625\u0644\u0649 \u0645\u062d\u0627\u0648\u0644\u0629 \u062a\u062d\u0645\u064a\u0644 \u0627\u0644\u0645\u0644\u0641 \u0639\u0644\u0649 \u0635\u0641\u062d\u0629 \u0641\u0627\u0631\u063a\u0629.\nerror-javascript-conflict-outdated = \u064a\u0645\u0643\u0646\u0643 \u0623\u064a\u0636\u064b\u0627 \u0645\u062d\u0627\u0648\u0644\u0629 \u062a\u062d\u0645\u064a\u0644 \u0646\u0633\u062e\u0629 \u0623\u062d\u062f\u062b \u0645\u0646 \u0631\u0641\u0644 \u0627\u0644\u062a\u064a \u0642\u062f \u062a\u062d\u0644 \u0627\u0644\u0645\u0634\u0643\u0644\u0629 (\u0627\u0644\u0646\u0633\u062e\u0629 \u0627\u0644\u062d\u0627\u0644\u064a\u0629 \u0642\u062f\u064a\u0645\u0629: { $buildDate }).\nerror-csp-conflict =\n \u0648\u0627\u062c\u0647\u062a \u0631\u0641\u0644 \u0645\u0634\u0643\u0644\u0629 \u0631\u0626\u064a\u0633\u064a\u0629 \u0623\u062b\u0646\u0627\u0621 \u0645\u062d\u0627\u0648\u0644\u0629 \u0627\u0644\u062a\u0647\u064a\u0626\u0629.\n \u0644\u0627 \u062a\u0633\u0645\u062d \u0633\u064a\u0627\u0633\u0629 \u0623\u0645\u0627\u0646 \u0627\u0644\u0645\u062d\u062a\u0648\u0649 \u0644\u062e\u0627\u062f\u0645 \u0627\u0644\u0648\u064a\u0628 \u0647\u0630\u0627 \u0628\u062a\u0634\u063a\u064a\u0644 \u0645\u0643\u0648\u0646 ".wasm" \u0627\u0644\u0645\u0637\u0644\u0648\u0628.\n \u0625\u0630\u0627 \u0643\u0646\u062a \u0645\u0633\u0624\u0648\u0644 \u0627\u0644\u062e\u0627\u062f\u0645\u060c \u064a\u0631\u062c\u0649 \u0627\u0644\u0631\u062c\u0648\u0639 \u0625\u0644\u0649 \u0631\u0641\u0644 \u0648\u064a\u0643\u064a \u0644\u0644\u062d\u0635\u0648\u0644 \u0639\u0644\u0649 \u0627\u0644\u0645\u0633\u0627\u0639\u062f\u0629.\nerror-unknown =\n \u0648\u0627\u062c\u0647\u062a \u0631\u0648\u0644 \u0645\u0634\u0643\u0644\u0629 \u0631\u0626\u064a\u0633\u064a\u0629 \u0623\u062b\u0646\u0627\u0621 \u0645\u062d\u0627\u0648\u0644\u0629 \u0639\u0631\u0636 \u0645\u062d\u062a\u0648\u0649 \u0627\u0644\u0641\u0644\u0627\u0634 \u0647\u0630\u0627.\n { $outdated ->\n [true] \u0625\u0630\u0627 \u0643\u0646\u062a \u0645\u0633\u0624\u0648\u0644 \u0627\u0644\u062e\u0627\u062f\u0645\u060c \u0627\u0644\u0631\u062c\u0627\u0621 \u0645\u062d\u0627\u0648\u0644\u0629 \u062a\u062d\u0645\u064a\u0644 \u0625\u0635\u062f\u0627\u0631 \u0623\u062d\u062f\u062b \u0645\u0646 \u0631\u0641\u0644 (\u0627\u0644\u0646\u0633\u062e\u0629 \u0627\u0644\u062d\u0627\u0644\u064a\u0629 \u0642\u062f\u064a\u0645\u0629: { $buildDate }).\n *[false] \u0644\u064a\u0633 \u0645\u0646 \u0627\u0644\u0645\u0641\u062a\u0631\u0636 \u0623\u0646 \u064a\u062d\u062f\u062b \u0647\u0630\u0627\u060c \u0644\u0630\u0644\u0643 \u0646\u062d\u0646 \u0646\u0642\u062f\u0631 \u062d\u0642\u064b\u0627 \u0625\u0630\u0627 \u0642\u0645\u062a \u0628\u0627\u0644\u062a\u0628\u0644\u064a\u063a \u0639\u0646 \u0627\u0644\u062e\u0637\u0623!\n }\n',"save-manager.ftl":"save-delete-prompt = \u0647\u0644 \u0623\u0646\u062a \u0645\u062a\u0623\u0643\u062f \u0623\u0646\u0643 \u062a\u0631\u064a\u062f \u062d\u0630\u0641 \u0645\u0644\u0641 \u062d\u0641\u0638 \u0627\u0644\u0644\u0639\u0628\u0629 \u0647\u0630\u0627\u061f\nsave-reload-prompt =\n \u0627\u0644\u0637\u0631\u064a\u0642\u0629 \u0627\u0644\u0648\u062d\u064a\u062f\u0629 \u0644\u0640 { $action ->\n [delete] \u062d\u0630\u0641\n *[replace] \u0627\u0633\u062a\u0628\u062f\u0627\u0644\n } \u0647\u0630\u0627 \u0627\u0644\u0645\u0644\u0641 \u0627\u0644\u062d\u0641\u0638 \u062f\u0648\u0646 \u062a\u0636\u0627\u0631\u0628 \u0645\u062d\u062a\u0645\u0644 \u0647\u064a \u0625\u0639\u0627\u062f\u0629 \u062a\u062d\u0645\u064a\u0644 \u0647\u0630\u0627 \u0627\u0644\u0645\u062d\u062a\u0648\u0649. \u0647\u0644 \u062a\u0631\u063a\u0628 \u0641\u064a \u0627\u0644\u0645\u062a\u0627\u0628\u0639\u0629 \u0639\u0644\u0649 \u0623\u064a \u062d\u0627\u0644\u061f\nsave-download = \u062a\u062d\u0645\u064a\u0644\nsave-replace = \u0627\u0633\u062a\u0628\u062f\u0627\u0644\nsave-delete = \u062d\u0630\u0641\nsave-backup-all = \u062a\u062d\u0645\u064a\u0644 \u062c\u0645\u064a\u0639 \u0627\u0644\u0645\u0644\u0641\u0627\u062a \u0627\u0644\u0645\u062d\u0641\u0648\u0638\u0629\n","volume-controls.ftl":"volume-controls = \u0627\u0644\u062a\u062d\u0643\u0645 \u0628\u0627\u0644\u0635\u0648\u062a\nvolume-controls-mute = \u0643\u062a\u0645\nvolume-controls-volume = \u0645\u0633\u062a\u0648\u0649 \u0627\u0644\u0635\u0648\u062a\n"},"ca-ES":{"context_menu.ftl":"context-menu-download-swf = Baixa el fitxer .swf\ncontext-menu-copy-debug-info = Copia la informaci\xf3 de depuraci\xf3\ncontext-menu-open-save-manager = Obre el gestor d'emmagatzematge\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] Quant a l'extensi\xf3 de Ruffle ({ $version })\n *[other] Quant a Ruffle ({ $version })\n }\ncontext-menu-hide = Amaga aquest men\xfa\ncontext-menu-exit-fullscreen = Surt de la pantalla completa\ncontext-menu-enter-fullscreen = Pantalla completa\ncontext-menu-volume-controls = Controls de volum\n","messages.ftl":"message-cant-embed =\n Ruffle no ha pogut executar el contingut Flash incrustat en aquesta p\xe0gina.\n Podeu provar d'obrir el fitxer en una pestanya a part per evitar aquest problema.\npanic-title = Alguna cosa ha fallat :(\nmore-info = M\xe9s informaci\xf3\nrun-anyway = Reprodueix igualment\ncontinue = Continua\nreport-bug = Informa d'un error\nupdate-ruffle = Actualitza Ruffle\nruffle-demo = Demostraci\xf3 web\nruffle-desktop = Aplicaci\xf3 d'escriptori\nruffle-wiki = Obre la wiki de Ruffle\nenable-hardware-acceleration = Sembla que l'acceleraci\xf3 per maquinari no est\xe0 activada. Tot i que Ruffle podria funcionar, \xe9s probable que ho faci molt lentament. Pots trobar informaci\xf3 sobre com activar l'acceleraci\xf3 per maquinari al seg\xfcent enlla\xe7.\nview-error-details = Mostra detalls de l'error\nopen-in-new-tab = Obre en una pestanya nova\nclick-to-unmute = Feu clic per activar el so\nerror-file-protocol =\n Sembla que esteu executant Ruffle al protocol \"file:\".\n Aix\xf2 no funcionar\xe0 perqu\xe8 els navegadors bloquegen moltes caracter\xedstiques per raons de seguretat. En comptes d'aix\xf2, us suggerim que configureu un servidor local o b\xe9 utilitzeu la demostraci\xf3 web o l'aplicaci\xf3 d'escriptori.\nerror-javascript-config =\n Ruffle ha topat amb un problema greu a causa d'una configuraci\xf3 JavaScript err\xf2nia.\n Si sou l'administrador del servidor, us suggerim que comproveu els detalls de l'error per determinar el par\xe0metre culpable.\n Tamb\xe9 podeu consultar la wiki del Ruffle per obtenir ajuda.\nerror-wasm-not-found =\n Ruffle no ha pogut carregar el component de fitxer \".wasm\" necessari.\n Si sou l'administrador del servidor, si us plau, comproveu que el fitxer ha estat carregat correctament.\n Si el problema continua, \xe9s possible que h\xe0giu d'utilitzar el par\xe1metre \"publicPath\": us preguem que consulteu la wiki de Ruffle per obtenir ajuda.\nerror-wasm-mime-type =\n Ruffle ha topat amb un problema greu mentre provava d'inicialitzar-se.\n Aquest servidor no est\xe0 servint els fitxers \".wasm\" amb el tipus MIME adequat.\n Si sou l'administrador del servidor, us preguem que consulteu la wiki de Ruffle per obtenir ajuda.\nerror-swf-fetch =\n Ruffle no ha pogut carregar el fitxer SWF Flash.\n La ra\xf3 m\xe9s probable \xe9s que el fitxer ja no existeixi, aix\xed que no hi ha res que el Ruffle pugui carregar.\n Proveu de contactar a l'administrador del lloc per obtenir ajuda.\nerror-swf-cors =\n Ruffle no ha pogut carregar el fitxer SWF Flash.\n \xc9s probable que l'acc\xe9s a la c\xe0rrega hagi estat denegat per una pol\xedtica CORS.\n Si sou l'administrador del servidor, us preguem que consulteu la wiki del Ruffle per obtenir ajuda.\nerror-wasm-cors =\n Ruffle no ha pogut carregar el component de fitxer \".wasm\" necessari.\n \xc9s probable que l'acc\xe9s a la c\xe0rrega hagi estat denegat per una pol\xedtica CORS.\n Si sou l'administrador del servidor, us preguem que consulteu la wiki del Ruffle per obtenir ajuda.\nerror-wasm-invalid =\n Ruffle ha topat amb un problema greu mentre provava d'inicialitzar-se.\n Sembla que a aquest lloc li manquen fitxers o aquests no s\xf3n v\xe0lids per a l'execuci\xf3 de Ruffle.\n Si sou l'administrador del servidor, us preguem que consulteu la wiki de Ruffle per obtenir ajuda.\nerror-wasm-download =\n Ruffle ha topat amb un problema greu mentre provava d'inicialitzar-se.\n Aix\xf2 sovint aix\xf2 pot resoldre's sol, aix\xed que podeu provar de recarregar la p\xe0gina.\n En cas contrari, us preguem que contacteu l'administrador del lloc.\nerror-wasm-disabled-on-edge =\n Ruffle no ha pogut carregar el component de fitxer \".wasm\" necessari.\n Per a arreglar-ho, proveu d'obrir els par\xe0metres del navegador, feu clic sobre \"Privadesa, cerca i serveis\", i desactiveu \"Prevenci\xf3 de seguiment\".\n Aix\xf2 permetr\xe0 que el vostre navegador carregui els fitxers \".wasm\" necessaris.\n Si el problema continua, possiblement haureu d'utilitzar un altre navegador.\nerror-javascript-conflict =\n Ruffle ha topat amb un problema greu mentre provava d'inicialitzar-se.\n Sembla que aquest lloc fa servir codi JavaScript que entra en conflicte amb Ruffle.\n Si sou l'administrador del servidor, us preguem que consulteu la wiki de Ruffle per obtenir ajuda.\nerror-javascript-conflict-outdated = Tamb\xe9 podeu provar de carregar una versi\xf3 m\xe9s recent de Ruffle que podria resoldre el problema (la compilaci\xf3 actual est\xe0 desactualitzada: { $buildDate }).\nerror-csp-conflict =\n Ruffle ha topat amb un problema greu mentre provava d'inicialitzar-se.\n La pol\xedtica de seguretat del contingut (CSP) no permet l'execuci\xf3 del component \".wasm\" necessari.\n Si sou l'administrador del servidor, us preguem que consulteu la wiki de Ruffle per obtenir ajuda.\nerror-unknown =\n Ruffle ha topat amb un problema greu mentre provava de mostrar aquest contingut Flash.\n { $outdated ->\n [true] Si sou l'administrador del servidor, us preguem que proveu de carregar una versi\xf3 m\xe9s recent de Ruffle (la compilaci\xf3 actual est\xe0 desactualitzada: { $buildDate }).\n *[false] Aix\xf2 no hauria d'haver passat, aix\xed que us agrair\xedem molt que n'inform\xe9ssiu l'error!\n }\n","save-manager.ftl":"save-delete-prompt = Segur que vols esborrar aquest fitxer desat?\nsave-reload-prompt =\n L'\xfanica forma d{ $action ->\n [delete] 'eliminar\n *[replace] e substituir\n } aquest fitxer desat sense crear un potencial conflicte \xe9s recarregant el contingut. Voleu continuar igualment?\nsave-download = Baixa\nsave-replace = Substitueix\nsave-delete = Elimina\nsave-backup-all = Baixa tots els fitxers desats\n","volume-controls.ftl":"volume-controls = Controls de volum\nvolume-controls-mute = Silenci\nvolume-controls-volume = Volum\n"},"cs-CZ":{"context_menu.ftl":"context-menu-download-swf = St\xe1hnout .swf\ncontext-menu-copy-debug-info = Zkop\xedrovat debug info\ncontext-menu-open-save-manager = Otev\u0159\xedt spr\xe1vce ulo\u017een\xed\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] O Ruffle roz\u0161\xed\u0159en\xed ({ $version })\n *[other] O Ruffle ({ $version })\n }\ncontext-menu-hide = Skr\xfdt menu\ncontext-menu-exit-fullscreen = Ukon\u010dit re\u017eim cel\xe9 obrazovky\ncontext-menu-enter-fullscreen = P\u0159ej\xedt do re\u017eimu cel\xe9 obrazovky\ncontext-menu-volume-controls = Ovl\xe1d\xe1n\xed hlasitosti\n","messages.ftl":'message-cant-embed =\n Ruffle nemohl spustit Flash vlo\u017een\xfd na t\xe9to str\xe1nce.\n M\u016f\u017eete se pokusit otev\u0159\xedt soubor na samostatn\xe9 kart\u011b, abyste se vyhnuli tomuto probl\xe9mu.\npanic-title = N\u011bco se pokazilo :(\nmore-info = Dal\u0161\xed informace\nrun-anyway = P\u0159esto spustit\ncontinue = Pokra\u010dovat\nreport-bug = Nahl\xe1sit chybu\nupdate-ruffle = Aktualizovat Ruffle\nruffle-demo = Web Demo\nruffle-desktop = Desktopov\xe1 aplikace\nruffle-wiki = Zobrazit Ruffle Wiki\nenable-hardware-acceleration = Zd\xe1 se, \u017ee hardwarov\xe1 akcelerace nen\xed povolena. I kdy\u017e Ruffle funguje spr\xe1vn\u011b, m\u016f\u017ee b\xfdt nep\u0159im\u011b\u0159en\u011b pomal\xfd. Jak povolit hardwarovou akceleraci zjist\xedte na tomto odkazu.\nview-error-details = Zobrazit podrobnosti o chyb\u011b\nopen-in-new-tab = Otev\u0159\xedt na nov\xe9 kart\u011b\nclick-to-unmute = Kliknut\xedm zru\u0161\xedte ztlumen\xed\nerror-file-protocol =\n Zd\xe1 se, \u017ee pou\u017e\xedv\xe1te Ruffle na protokolu "file:".\n To nen\xed mo\u017en\xe9, proto\u017ee prohl\xed\u017ee\u010de blokuj\xed fungov\xe1n\xed mnoha funkc\xed z bezpe\u010dnostn\xedch d\u016fvod\u016f.\n Nam\xedsto toho v\xe1m doporu\u010dujeme nastavit lok\xe1ln\xed server nebo pou\u017e\xedt web demo \u010di desktopovou aplikaci.\nerror-javascript-config =\n Ruffle narazil na probl\xe9m v d\u016fsledku nespr\xe1vn\xe9 konfigurace JavaScriptu.\n Pokud jste spr\xe1vcem serveru, doporu\u010dujeme v\xe1m zkontrolovat podrobnosti o chyb\u011b, abyste zjistili, kter\xfd parametr je vadn\xfd.\n Pomoc m\u016f\u017eete z\xedskat tak\xe9 na wiki Ruffle.\nerror-wasm-not-found =\n Ruffle se nepoda\u0159ilo na\u010d\xedst po\u017eadovanou komponentu souboru \u201e.wasm\u201c.\n Pokud jste spr\xe1vcem serveru, zkontrolujte, zda byl soubor spr\xe1vn\u011b nahr\xe1n.\n Pokud probl\xe9m p\u0159etrv\xe1v\xe1, mo\u017en\xe1 budete muset pou\u017e\xedt nastaven\xed \u201epublicPath\u201c: pomoc naleznete na wiki Ruffle.\nerror-wasm-mime-type =\n Ruffle narazil na probl\xe9m p\u0159i pokusu o inicializaci.\n Tento webov\xfd server neposkytuje soubory \u201e.wasm\u201c se spr\xe1vn\xfdm typem MIME.\n Pokud jste spr\xe1vcem serveru, n\xe1pov\u011bdu najdete na Ruffle wiki.\nerror-swf-fetch =\n Ruffle se nepoda\u0159ilo na\u010d\xedst SWF soubor Flash.\n Nejpravd\u011bpodobn\u011bj\u0161\xedm d\u016fvodem je, \u017ee soubor ji\u017e neexistuje, tak\u017ee Ruffle nem\xe1 co na\u010d\xedst.\n Zkuste po\u017e\xe1dat o pomoc spr\xe1vce webu.\nerror-swf-cors =\n Ruffle se nepoda\u0159ilo na\u010d\xedst SWF soubor Flash.\n P\u0159\xedstup k na\u010d\xedt\xe1n\xed byl pravd\u011bpodobn\u011b zablokov\xe1n politikou CORS.\n Pokud jste spr\xe1vcem serveru, n\xe1pov\u011bdu najdete na Ruffle wiki.\nerror-wasm-cors =\n Ruffle se nepoda\u0159ilo na\u010d\xedst po\u017eadovanou komponentu souboru \u201e.wasm\u201c.\n P\u0159\xedstup k na\u010d\xedt\xe1n\xed byl pravd\u011bpodobn\u011b zablokov\xe1n politikou CORS.\n Pokud jste spr\xe1vcem serveru, n\xe1pov\u011bdu najdete na Ruffle wiki.\nerror-wasm-invalid =\n Ruffle narazil na probl\xe9m p\u0159i pokusu o inicializaci.\n Zd\xe1 se, \u017ee na t\xe9to str\xe1nce chyb\xed nebo jsou neplatn\xe9 soubory ke spu\u0161t\u011bn\xed Ruffle.\n Pokud jste spr\xe1vcem serveru, n\xe1pov\u011bdu najdete na Ruffle wiki.\nerror-wasm-download =\n Ruffle narazil na probl\xe9m p\u0159i pokusu o inicializaci.\n Probl\xe9m se m\u016f\u017ee vy\u0159e\u0161it i s\xe1m, tak\u017ee m\u016f\u017eete zkusit str\xe1nku na\u010d\xedst znovu.\n V opa\u010dn\xe9m p\u0159\xedpad\u011b kontaktujte administr\xe1tora str\xe1nky.\nerror-wasm-disabled-on-edge =\n Ruffle se nepoda\u0159ilo na\u010d\xedst po\u017eadovanou komponentu souboru \u201e.wasm\u201c.\n Chcete-li tento probl\xe9m vy\u0159e\u0161it, zkuste otev\u0159\xedt nastaven\xed prohl\xed\u017ee\u010de, klikn\u011bte na polo\u017eku \u201eOchrana osobn\xedch \xfadaj\u016f, vyhled\xe1v\xe1n\xed a slu\u017eby\u201c, p\u0159ejd\u011bte dol\u016f a vypn\u011bte mo\u017enost \u201eZvy\u0161te svou bezpe\u010dnost na webu\u201c.\n Va\u0161emu prohl\xed\u017ee\u010di to umo\u017en\xed na\u010d\xedst po\u017eadovan\xe9 soubory \u201e.wasm\u201c.\n Pokud probl\xe9m p\u0159etrv\xe1v\xe1, budete mo\u017en\xe1 muset pou\u017e\xedt jin\xfd prohl\xed\u017ee\u010d.\nerror-javascript-conflict =\n Ruffle narazil na probl\xe9m p\u0159i pokusu o inicializaci.\n Zd\xe1 se, \u017ee tato str\xe1nka pou\u017e\xedv\xe1 k\xf3d JavaScript, kter\xfd je v konfliktu s Ruffle.\n Pokud jste spr\xe1vcem serveru, doporu\u010dujeme v\xe1m zkusit na\u010d\xedst soubor na pr\xe1zdnou str\xe1nku.\nerror-javascript-conflict-outdated = M\u016f\u017eete se tak\xe9 pokusit nahr\xe1t nov\u011bj\u0161\xed verzi Ruffle, kter\xe1 m\u016f\u017ee dan\xfd probl\xe9m vy\u0159e\u0161it (aktu\xe1ln\xed build je zastaral\xfd: { $buildDate }).\nerror-csp-conflict =\n Ruffle narazil na probl\xe9m p\u0159i pokusu o inicializaci.\n Z\xe1sady zabezpe\u010den\xed obsahu tohoto webov\xe9ho serveru nepovoluj\xed spu\u0161t\u011bn\xed po\u017eadovan\xe9 komponenty \u201e.wasm\u201c.\n Pokud jste spr\xe1vcem serveru, n\xe1pov\u011bdu najdete na Ruffle wiki.\nerror-unknown =\n Ruffle narazil na probl\xe9m p\u0159i pokusu zobrazit tento Flash obsah.\n { $outdated ->\n [true] Pokud jste spr\xe1vcem serveru, zkuste nahr\xe1t nov\u011bj\u0161\xed verzi Ruffle (aktu\xe1ln\xed build je zastaral\xfd: { $buildDate }).\n *[false] Toto by se nem\u011blo st\xe1t, tak\u017ee bychom opravdu ocenili, kdybyste mohli nahl\xe1sit chybu!\n }\n',"save-manager.ftl":"save-delete-prompt = Opravdu chcete odstranit tento soubor s ulo\u017een\xfdmi pozicemi?\nsave-reload-prompt =\n Jedin\xfd zp\u016fsob, jak { $action ->\n [delete] vymazat\n *[replace] nahradit\n } tento soubor s ulo\u017een\xfdmi pozicemi bez potenci\xe1ln\xedho konfliktu je op\u011btovn\xe9 na\u010dten\xed tohoto obsahu. Chcete p\u0159esto pokra\u010dovat?\nsave-download = St\xe1hnout\nsave-replace = Nahradit\nsave-delete = Vymazat\nsave-backup-all = St\xe1hnout v\u0161echny soubory s ulo\u017een\xfdmi pozicemi\n","volume-controls.ftl":"volume-controls = Ovl\xe1d\xe1n\xed hlasitosti\nvolume-controls-mute = Ztlumit\nvolume-controls-volume = Hlasitost\n"},"de-DE":{"context_menu.ftl":"context-menu-download-swf = .swf herunterladen\ncontext-menu-copy-debug-info = Debug-Info kopieren\ncontext-menu-open-save-manager = Dateimanager \xf6ffnen\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] \xdcber Ruffle Erweiterung ({ $version })\n *[other] \xdcber Ruffle ({ $version })\n }\ncontext-menu-hide = Men\xfc ausblenden\ncontext-menu-exit-fullscreen = Vollbild verlassen\ncontext-menu-enter-fullscreen = Vollbildmodus aktivieren\ncontext-menu-volume-controls = Lautst\xe4rke einstellen\n","messages.ftl":'message-cant-embed =\n Ruffle konnte den Flash in dieser Seite nicht ausf\xfchren.\n Du kannst versuchen, die Datei in einem separaten Tab zu \xf6ffnen, um dieses Problem zu umgehen.\npanic-title = Etwas ist schief gelaufen\nmore-info = Weitere Informationen\nrun-anyway = Trotzdem ausf\xfchren\ncontinue = Fortfahren\nreport-bug = Fehler melden\nupdate-ruffle = Ruffle aktuallisieren\nruffle-demo = Web-Demo\nruffle-desktop = Desktop-Anwendung\nruffle-wiki = Ruffle-Wiki anzeigen\nview-error-details = Fehlerdetails anzeigen\nopen-in-new-tab = In einem neuen Tab \xf6ffnen\nclick-to-unmute = Klicke zum Entmuten\nerror-file-protocol =\n Es scheint, dass Sie Ruffle auf dem "file:"-Protokoll ausf\xfchren.\n Dies funktioniert nicht so, als Browser viele Funktionen aus Sicherheitsgr\xfcnden blockieren.\n Stattdessen laden wir Sie ein, einen lokalen Server einzurichten oder entweder die Webdemo oder die Desktop-Anwendung zu verwenden.\nerror-javascript-config =\n Ruffle ist aufgrund einer falschen JavaScript-Konfiguration auf ein gro\xdfes Problem gesto\xdfen.\n Wenn du der Server-Administrator bist, laden wir dich ein, die Fehlerdetails zu \xfcberpr\xfcfen, um herauszufinden, welcher Parameter fehlerhaft ist.\n Sie k\xf6nnen auch das Ruffle-Wiki f\xfcr Hilfe konsultieren.\nerror-wasm-not-found =\n Ruffle konnte die erforderliche ".wasm"-Datei-Komponente nicht laden.\n Wenn Sie der Server-Administrator sind, stellen Sie bitte sicher, dass die Datei korrekt hochgeladen wurde.\n Wenn das Problem weiterhin besteht, m\xfcssen Sie unter Umst\xe4nden die "publicPath"-Einstellung verwenden: Bitte konsultieren Sie das Ruffle-Wiki f\xfcr Hilfe.\nerror-wasm-mime-type =\n Ruffle ist auf ein gro\xdfes Problem beim Initialisieren gesto\xdfen.\n Dieser Webserver dient nicht ". asm"-Dateien mit dem korrekten MIME-Typ.\n Wenn Sie der Server-Administrator sind, konsultieren Sie bitte das Ruffle-Wiki f\xfcr Hilfe.\nerror-swf-fetch =\n Ruffle konnte die Flash-SWF-Datei nicht laden.\n Der wahrscheinlichste Grund ist, dass die Datei nicht mehr existiert, so dass Ruffle nicht geladen werden kann.\n Kontaktieren Sie den Website-Administrator f\xfcr Hilfe.\nerror-swf-cors =\n Ruffle konnte die Flash-SWF-Datei nicht laden.\n Der Zugriff auf den Abruf wurde wahrscheinlich durch die CORS-Richtlinie blockiert.\n Wenn Sie der Server-Administrator sind, konsultieren Sie bitte das Ruffle-Wiki f\xfcr Hilfe.\nerror-wasm-cors =\n Ruffle konnte die Flash-SWF-Datei nicht laden.\n Der Zugriff auf den Abruf wurde wahrscheinlich durch die CORS-Richtlinie blockiert.\n Wenn Sie der Server-Administrator sind, konsultieren Sie bitte das Ruffle-Wiki f\xfcr Hilfe.\nerror-wasm-invalid =\n Ruffle ist auf ein gro\xdfes Problem beim Initialisieren gesto\xdfen.\n Dieser Webserver dient nicht ". asm"-Dateien mit dem korrekten MIME-Typ.\n Wenn Sie der Server-Administrator sind, konsultieren Sie bitte das Ruffle-Wiki f\xfcr Hilfe.\nerror-wasm-download =\n Ruffle ist auf ein gro\xdfes Problem gesto\xdfen, w\xe4hrend er versucht hat zu initialisieren.\n Dies kann sich oft selbst beheben, so dass Sie versuchen k\xf6nnen, die Seite neu zu laden.\n Andernfalls kontaktieren Sie bitte den Website-Administrator.\nerror-wasm-disabled-on-edge =\n Ruffle konnte die erforderliche ".wasm"-Datei-Komponente nicht laden.\n Um dies zu beheben, versuche die Einstellungen deines Browsers zu \xf6ffnen, klicke auf "Privatsph\xe4re, Suche und Dienste", scrollen nach unten und schalte "Verbessere deine Sicherheit im Web" aus.\n Dies erlaubt Ihrem Browser die erforderlichen ".wasm"-Dateien zu laden.\n Wenn das Problem weiterhin besteht, m\xfcssen Sie m\xf6glicherweise einen anderen Browser verwenden.\nerror-javascript-conflict =\n Ruffle ist auf ein gro\xdfes Problem beim Initialisieren gesto\xdfen.\n Es scheint, als ob diese Seite JavaScript-Code verwendet, der mit Ruffle kollidiert.\n Wenn Sie der Server-Administrator sind, laden wir Sie ein, die Datei auf einer leeren Seite zu laden.\nerror-javascript-conflict-outdated = Du kannst auch versuchen, eine neuere Version von Ruffle hochzuladen, die das Problem umgehen k\xf6nnte (aktuelle Version ist veraltet: { $buildDate }).\nerror-csp-conflict =\n Ruffle ist auf ein gro\xdfes Problem beim Initialisieren gesto\xdfen.\n Dieser Webserver dient nicht ". asm"-Dateien mit dem korrekten MIME-Typ.\n Wenn Sie der Server-Administrator sind, konsultieren Sie bitte das Ruffle-Wiki f\xfcr Hilfe.\nerror-unknown =\n Bei dem Versuch, diesen Flash-Inhalt anzuzeigen, ist Ruffle auf ein gro\xdfes Problem gesto\xdfen.\n { $outdated ->\n [true] Wenn Sie der Server-Administrator sind, Bitte versuchen Sie, eine neuere Version von Ruffle hochzuladen (aktuelle Version ist veraltet: { $buildDate }).\n *[false] Dies soll nicht passieren, deshalb w\xfcrden wir uns sehr dar\xfcber freuen, wenn Sie einen Fehler melden k\xf6nnten!\n }\n',"save-manager.ftl":"save-delete-prompt = Sind Sie sicher, dass Sie diese Speicherdatei l\xf6schen m\xf6chten?\nsave-reload-prompt =\n Der einzige Weg zu { $action ->\n [delete] l\xf6schen\n *[replace] ersetzen\n } diese Speicherdatei ohne m\xf6glichen Konflikt ist das erneute Laden dieses Inhalts. M\xf6chten Sie trotzdem fortfahren?\nsave-download = Herunterladen\nsave-replace = Ersetzen\nsave-delete = L\xf6schen\nsave-backup-all = Alle gespeicherten Dateien herunterladen\n","volume-controls.ftl":"volume-controls = Lautst\xe4rkeeinstellungen\nvolume-controls-mute = Stummschalten\nvolume-controls-volume = Lautst\xe4rke\n"},"en-US":{"context_menu.ftl":"context-menu-download-swf = Download .swf\ncontext-menu-copy-debug-info = Copy debug info\ncontext-menu-open-save-manager = Open Save Manager\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] About Ruffle Extension ({$version})\n *[other] About Ruffle ({$version})\n }\ncontext-menu-hide = Hide this menu\ncontext-menu-exit-fullscreen = Exit fullscreen\ncontext-menu-enter-fullscreen = Enter fullscreen\ncontext-menu-volume-controls = Volume controls\n","messages.ftl":'message-cant-embed =\n Ruffle wasn\'t able to run the Flash embedded in this page.\n You can try to open the file in a separate tab, to sidestep this issue.\npanic-title = Something went wrong :(\nmore-info = More info\nrun-anyway = Run anyway\ncontinue = Continue\nreport-bug = Report Bug\nupdate-ruffle = Update Ruffle\nruffle-demo = Web Demo\nruffle-desktop = Desktop Application\nruffle-wiki = View Ruffle Wiki\nenable-hardware-acceleration = It looks like hardware acceleration is not enabled. While Ruffle may work, it could be unreasonably slow. You can find out how to enable hardware acceleration by following this link.\nview-error-details = View Error Details\nopen-in-new-tab = Open in a new tab\nclick-to-unmute = Click to unmute\nerror-file-protocol =\n It appears you are running Ruffle on the "file:" protocol.\n This doesn\'t work as browsers block many features from working for security reasons.\n Instead, we invite you to setup a local server or either use the web demo or the desktop application.\nerror-javascript-config =\n Ruffle has encountered a major issue due to an incorrect JavaScript configuration.\n If you are the server administrator, we invite you to check the error details to find out which parameter is at fault.\n You can also consult the Ruffle wiki for help.\nerror-wasm-not-found =\n Ruffle failed to load the required ".wasm" file component.\n If you are the server administrator, please ensure the file has correctly been uploaded.\n If the issue persists, you may need to use the "publicPath" setting: please consult the Ruffle wiki for help.\nerror-wasm-mime-type =\n Ruffle has encountered a major issue whilst trying to initialize.\n This web server is not serving ".wasm" files with the correct MIME type.\n If you are the server administrator, please consult the Ruffle wiki for help.\nerror-swf-fetch =\n Ruffle failed to load the Flash SWF file.\n The most likely reason is that the file no longer exists, so there is nothing for Ruffle to load.\n Try contacting the website administrator for help.\nerror-swf-cors =\n Ruffle failed to load the Flash SWF file.\n Access to fetch has likely been blocked by CORS policy.\n If you are the server administrator, please consult the Ruffle wiki for help.\nerror-wasm-cors =\n Ruffle failed to load the required ".wasm" file component.\n Access to fetch has likely been blocked by CORS policy.\n If you are the server administrator, please consult the Ruffle wiki for help.\nerror-wasm-invalid =\n Ruffle has encountered a major issue whilst trying to initialize.\n It seems like this page has missing or invalid files for running Ruffle.\n If you are the server administrator, please consult the Ruffle wiki for help.\nerror-wasm-download =\n Ruffle has encountered a major issue whilst trying to initialize.\n This can often resolve itself, so you can try reloading the page.\n Otherwise, please contact the website administrator.\nerror-wasm-disabled-on-edge =\n Ruffle failed to load the required ".wasm" file component.\n To fix this, try opening your browser\'s settings, clicking "Privacy, search, and services", scrolling down, and turning off "Enhance your security on the web".\n This will allow your browser to load the required ".wasm" files.\n If the issue persists, you might have to use a different browser.\nerror-javascript-conflict =\n Ruffle has encountered a major issue whilst trying to initialize.\n It seems like this page uses JavaScript code that conflicts with Ruffle.\n If you are the server administrator, we invite you to try loading the file on a blank page.\nerror-javascript-conflict-outdated = You can also try to upload a more recent version of Ruffle that may circumvent the issue (current build is outdated: {$buildDate}).\nerror-csp-conflict =\n Ruffle has encountered a major issue whilst trying to initialize.\n This web server\'s Content Security Policy does not allow the required ".wasm" component to run.\n If you are the server administrator, please consult the Ruffle wiki for help.\nerror-unknown =\n Ruffle has encountered a major issue whilst trying to display this Flash content.\n {$outdated ->\n [true] If you are the server administrator, please try to upload a more recent version of Ruffle (current build is outdated: {$buildDate}).\n *[false] This isn\'t supposed to happen, so we\'d really appreciate if you could file a bug!\n }\n',"save-manager.ftl":"save-delete-prompt = Are you sure you want to delete this save file?\nsave-reload-prompt =\n The only way to {$action ->\n [delete] delete\n *[replace] replace\n } this save file without potential conflict is to reload this content. Do you wish to continue anyway?\nsave-download = Download\nsave-replace = Replace\nsave-delete = Delete\nsave-backup-all = Download all save files","volume-controls.ftl":"volume-controls = Volume controls\nvolume-controls-mute = Mute\nvolume-controls-volume = Volume\n"},"es-ES":{"context_menu.ftl":"context-menu-download-swf = Descargar .swf\ncontext-menu-copy-debug-info = Copiar Informaci\xf3n de depuraci\xf3n\ncontext-menu-open-save-manager = Abrir gestor de guardado\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] Sobre la extensi\xf3n de Ruffle ({ $version })\n *[other] Sobre Ruffle ({ $version })\n }\ncontext-menu-hide = Ocultar este men\xfa\ncontext-menu-exit-fullscreen = Salir de pantalla completa\ncontext-menu-enter-fullscreen = Entrar a pantalla completa\ncontext-menu-volume-controls = Controles de volumen\n","messages.ftl":'message-cant-embed =\n Ruffle no pudo ejecutar el Flash incrustado en esta p\xe1gina.\n Puedes intentar abrir el archivo en una pesta\xf1a aparte, para evitar este problema.\npanic-title = Algo sali\xf3 mal :(\nmore-info = M\xe1s info\nrun-anyway = Ejecutar de todos modos\ncontinue = Continuar\nreport-bug = Reportar un Error\nupdate-ruffle = Actualizar Ruffle\nruffle-demo = Demostraci\xf3n de web\nruffle-desktop = Aplicaci\xf3n de Desktop\nruffle-wiki = Ver la p\xe1gina wiki\nenable-hardware-acceleration = Al parecer, la aceleraci\xf3n de hardware no esta habilitada. Puede que Ruffle funcione, pero ser\xe1 extremadamente lento. Puedes averiguar como habilitar la aceleraci\xf3n de hardware al entrar al enlace.\nview-error-details = Ver los detalles del error\nopen-in-new-tab = Abrir en una pesta\xf1a nueva\nclick-to-unmute = Haz clic para dejar de silenciar\nerror-file-protocol =\n Parece que est\xe1 ejecutando Ruffle en el protocolo "archivo:".\n Esto no funciona porque los navegadores bloquean que muchas caracter\xedsticas funcionen por razones de seguridad.\n En su lugar, le invitamos a configurar un servidor local o bien usar la demostraci\xf3n web o la aplicaci\xf3n de desktop.\nerror-javascript-config =\n Ruffle ha encontrado un problema cr\xedtico debido a una configuraci\xf3n JavaScript incorrecta.\n Si usted es el administrador del servidor, le invitamos a comprobar los detalles del error para averiguar qu\xe9 par\xe1metro est\xe1 en falta.\n Tambi\xe9n puedes consultar la wiki de Ruffle para obtener ayuda.\nerror-wasm-not-found =\n Ruffle no pudo cargar el componente de archivo ".wasm" requerido.\n Si usted es el administrador del servidor, aseg\xfarese de que el archivo ha sido subido correctamente.\n Si el problema persiste, puede que necesite usar la configuraci\xf3n "publicPath": por favor consulte la wiki de Ruffle para obtener ayuda.\nerror-wasm-mime-type =\n Ruffle ha encontrado un problema cr\xedtico al intentar inicializar.\n Este servidor web no est\xe1 sirviendo archivos wasm" con el tipo MIME correcto.\n Si usted es el administrador del servidor, consulte la wiki de Ruffle para obtener ayuda.\nerror-swf-fetch =\n Ruffle no pudo cargar el archivo Flash SWF.\n La raz\xf3n m\xe1s probable es que el archivo ya no existe, as\xed que no hay nada para cargar Ruffle.\n Intente ponerse en contacto con el administrador del sitio web para obtener ayuda.\nerror-swf-cors =\n Ruffle no pudo cargar el archivo Flash SWF.\n Es probable que el acceso a la b\xfasqueda haya sido bloqueado por la pol\xedtica CORS.\n Si usted es el administrador del servidor, consulte la wiki de Ruffle para obtener ayuda.\nerror-wasm-cors =\n Ruffle no pudo cargar el archivo ".wasm."\n Es probable que el acceso a la b\xfasqueda o la llamada a la funci\xf3n fetch haya sido bloqueado por la pol\xedtica CORS.\n Si usted es el administrador del servidor, consulte la wiki de Ruffle para obtener ayuda.\nerror-wasm-invalid =\n Ruffle ha encontrado un problema cr\xedtico al intentar inicializar.\n Este servidor web no est\xe1 sirviendo archivos wasm" con el tipo Mime correcto.\n Si usted es el administrador del servidor, consulte la wiki de Ruffle para obtener ayuda.\nerror-wasm-download =\n Ruffle ha encontrado un problema cr\xedtico mientras intentaba inicializarse.\n Esto a menudo puede resolverse por s\xed mismo, as\xed que puede intentar recargar la p\xe1gina.\n De lo contrario, p\xf3ngase en contacto con el administrador del sitio web.\nerror-wasm-disabled-on-edge =\n Ruffle no pudo cargar el componente de archivo ".wasm" requerido.\n Para solucionar esto, intenta abrir la configuraci\xf3n de tu navegador, haciendo clic en "Privacidad, b\xfasqueda y servicios", desplaz\xe1ndote y apagando "Mejore su seguridad en la web".\n Esto permitir\xe1 a su navegador cargar los archivos ".wasm" necesarios.\n Si el problema persiste, puede que tenga que utilizar un navegador diferente.\nerror-javascript-conflict =\n Ruffle ha encontrado un problema cr\xedtico mientras intentaba inicializarse.\n Parece que esta p\xe1gina utiliza c\xf3digo JavaScript que entra en conflicto con Ruffle.\n Si usted es el administrador del servidor, le invitamos a intentar cargar el archivo en una p\xe1gina en blanco.\nerror-javascript-conflict-outdated = Tambi\xe9n puedes intentar subir una versi\xf3n m\xe1s reciente de Ruffle que puede eludir el problema (la versi\xf3n actual est\xe1 desactualizada: { $buildDate }).\nerror-csp-conflict =\n Ruffle encontr\xf3 un problema al intentar inicializarse.\n La Pol\xedtica de Seguridad de Contenido de este servidor web no permite el componente requerido ".wasm". \n Si usted es el administrador del servidor, por favor consulta la wiki de Ruffle para obtener ayuda.\nerror-unknown =\n Ruffle ha encontrado un problema al tratar de mostrar el contenido Flash.\n { $outdated ->\n [true] Si usted es el administrador del servidor, intenta cargar una version m\xe1s reciente de Ruffle (la version actual esta desactualizada: { $buildDate }).\n *[false] Esto no deberia suceder! apreciariamos que reportes el error!\n }\n',"save-manager.ftl":"save-delete-prompt = \xbfEst\xe1 seguro de querer eliminar este archivo de guardado?\nsave-reload-prompt =\n La \xfanica forma de { $action ->\n [delete] eliminar\n *[replace] sobreescribir\n } este archivo de guardado sin conflictos potenciales es reiniciando el contenido. \xbfDesea continuar de todos modos?\nsave-download = Descargar\nsave-replace = Sobreescribir\nsave-delete = Borrar\nsave-backup-all = Borrar todos los archivos de guardado\n","volume-controls.ftl":"volume-controls = Controles de volumen\nvolume-controls-mute = Silenciar\nvolume-controls-volume = Volumen\n"},"fr-FR":{"context_menu.ftl":"context-menu-download-swf = T\xe9l\xe9charger en tant que .swf\ncontext-menu-copy-debug-info = Copier les infos de d\xe9bogage\ncontext-menu-open-save-manager = Ouvrir le gestionnaire de stockage\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] \xc0 propos de l'Extension Ruffle ({ $version })\n *[other] \xc0 propos de Ruffle ({ $version })\n }\ncontext-menu-hide = Masquer ce menu\ncontext-menu-exit-fullscreen = Sortir du mode plein \xe9cran\ncontext-menu-enter-fullscreen = Afficher en plein \xe9cran\ncontext-menu-volume-controls = Contr\xf4les du volume\n","messages.ftl":"message-cant-embed =\n Ruffle n'a pas \xe9t\xe9 en mesure de lire le fichier Flash int\xe9gr\xe9 dans cette page.\n Vous pouvez essayer d'ouvrir le fichier dans un onglet isol\xe9, pour contourner le probl\xe8me.\npanic-title = Une erreur est survenue :(\nmore-info = Plus d'infos\nrun-anyway = Ex\xe9cuter quand m\xeame\ncontinue = Continuer\nreport-bug = Signaler le bug\nupdate-ruffle = Mettre \xe0 jour Ruffle\nruffle-demo = D\xe9mo en ligne\nruffle-desktop = Application de bureau\nruffle-wiki = Wiki de Ruffle\nenable-hardware-acceleration = Il semblerait que l'acc\xe9l\xe9ration mat\xe9rielle ne soit pas activ\xe9e. Cela n'emp\xeache g\xe9n\xe9ralement pas Ruffle de fonctionner, mais il peut \xeatre beaucoup plus lent. Vous pouvez trouver comment activer l'acc\xe9l\xe9ration mat\xe9rielle en suivant ce lien.\nview-error-details = D\xe9tails de l'erreur\nopen-in-new-tab = Ouvrir dans un nouvel onglet\nclick-to-unmute = Cliquez pour activer le son\nerror-file-protocol =\n Il semblerait que vous ex\xe9cutiez Ruffle sur le protocole \"file:\".\n Cela ne fonctionne pas car les navigateurs bloquent de nombreuses fonctionnalit\xe9s pour des raisons de s\xe9curit\xe9.\n Nous vous invitons soit \xe0 configurer un serveur local, soit \xe0 utiliser la d\xe9mo en ligne ou l'application de bureau.\nerror-javascript-config =\n Ruffle a rencontr\xe9 un probl\xe8me majeur en raison d'une configuration JavaScript incorrecte.\n Si vous \xeates l'administrateur du serveur, nous vous invitons \xe0 v\xe9rifier les d\xe9tails de l'erreur pour savoir quel est le param\xe8tre en cause.\n Vous pouvez \xe9galement consulter le wiki de Ruffle pour obtenir de l'aide.\nerror-wasm-not-found =\n Ruffle n'a pas r\xe9ussi \xe0 charger son fichier \".wasm\".\n Si vous \xeates l'administrateur du serveur, veuillez vous assurer que ce fichier a bien \xe9t\xe9 mis en ligne.\n Si le probl\xe8me persiste, il vous faudra peut-\xeatre utiliser le param\xe8tre \"publicPath\" : veuillez consulter le wiki de Ruffle pour obtenir de l'aide.\nerror-wasm-mime-type =\n Ruffle a rencontr\xe9 un probl\xe8me majeur durant sa phase d'initialisation.\n Ce serveur web ne renvoie pas le bon type MIME pour les fichiers \".wasm\".\n Si vous \xeates l'administrateur du serveur, veuillez consulter le wiki de Ruffle pour obtenir de l'aide.\nerror-swf-fetch =\n Ruffle n'a pas r\xe9ussi \xe0 charger le fichier Flash.\n La raison la plus probable est que le fichier n'existe pas ou plus.\n Vous pouvez essayer de prendre contact avec l'administrateur du site pour obtenir plus d'informations.\nerror-swf-cors =\n Ruffle n'a pas r\xe9ussi \xe0 charger le fichier Flash.\n La requ\xeate a probablement \xe9t\xe9 rejet\xe9e en raison de la configuration du CORS.\n Si vous \xeates l'administrateur du serveur, veuillez consulter le wiki de Ruffle pour obtenir de l'aide.\nerror-wasm-cors =\n Ruffle n'a pas r\xe9ussi \xe0 charger son fichier \".wasm\".\n La requ\xeate a probablement \xe9t\xe9 rejet\xe9e en raison de la configuration du CORS.\n Si vous \xeates l'administrateur du serveur, veuillez consulter le wiki de Ruffle pour obtenir de l'aide.\nerror-wasm-invalid =\n Ruffle a rencontr\xe9 un probl\xe8me majeur durant sa phase d'initialisation.\n Il semblerait que cette page comporte des fichiers manquants ou invalides pour ex\xe9cuter Ruffle.\n Si vous \xeates l'administrateur du serveur, veuillez consulter le wiki de Ruffle pour obtenir de l'aide.\nerror-wasm-download =\n Ruffle a rencontr\xe9 un probl\xe8me majeur durant sa phase d'initialisation.\n Le probl\xe8me d\xe9tect\xe9 peut souvent se r\xe9soudre de lui-m\xeame, donc vous pouvez essayer de recharger la page.\n Si le probl\xe8me persiste, veuillez prendre contact avec l'administrateur du site.\nerror-wasm-disabled-on-edge =\n Ruffle n'a pas r\xe9ussi \xe0 charger son fichier \".wasm\".\n Pour r\xe9soudre ce probl\xe8me, essayez d'ouvrir les param\xe8tres de votre navigateur et de cliquer sur \"Confidentialit\xe9, recherche et services\". Puis, vers le bas de la page, d\xe9sactivez l'option \"Am\xe9liorez votre s\xe9curit\xe9 sur le web\".\n Cela permettra \xe0 votre navigateur de charger les fichiers \".wasm\".\n Si le probl\xe8me persiste, vous devrez peut-\xeatre utiliser un autre navigateur.\nerror-javascript-conflict =\n Ruffle a rencontr\xe9 un probl\xe8me majeur durant sa phase d'initialisation.\n Il semblerait que cette page contienne du code JavaScript qui entre en conflit avec Ruffle.\n Si vous \xeates l'administrateur du serveur, nous vous invitons \xe0 essayer de charger le fichier dans une page vide.\nerror-javascript-conflict-outdated = Vous pouvez \xe9galement essayer de mettre en ligne une version plus r\xe9cente de Ruffle qui pourrait avoir corrig\xe9 le probl\xe8me (la version que vous utilisez est obsol\xe8te : { $buildDate }).\nerror-csp-conflict =\n Ruffle a rencontr\xe9 un probl\xe8me majeur durant sa phase d'initialisation.\n La strat\xe9gie de s\xe9curit\xe9 du contenu (CSP) de ce serveur web n'autorise pas l'ex\xe9cution de fichiers \".wasm\".\n Si vous \xeates l'administrateur du serveur, veuillez consulter le wiki de Ruffle pour obtenir de l'aide.\nerror-unknown =\n Ruffle a rencontr\xe9 un probl\xe8me majeur durant l'ex\xe9cution de ce contenu Flash.\n { $outdated ->\n [true] Si vous \xeates l'administrateur du serveur, veuillez essayer de mettre en ligne une version plus r\xe9cente de Ruffle (la version que vous utilisez est obsol\xe8te : { $buildDate }).\n *[false] Cela n'est pas cens\xe9 se produire, donc nous vous serions reconnaissants si vous pouviez nous signaler ce bug !\n }\n","save-manager.ftl":"save-delete-prompt = Voulez-vous vraiment supprimer ce fichier de sauvegarde ?\nsave-reload-prompt =\n La seule fa\xe7on de { $action ->\n [delete] supprimer\n *[replace] remplacer\n } ce fichier de sauvegarde sans conflit potentiel est de recharger ce contenu. Souhaitez-vous quand m\xeame continuer ?\nsave-download = T\xe9l\xe9charger\nsave-replace = Remplacer\nsave-delete = Supprimer\nsave-backup-all = T\xe9l\xe9charger tous les fichiers de sauvegarde\n","volume-controls.ftl":"volume-controls = Contr\xf4les du volume\nvolume-controls-mute = Muet\nvolume-controls-volume = Volume\n"},"he-IL":{"context_menu.ftl":"context-menu-download-swf = \u05d4\u05d5\u05e8\u05d3\u05ea \u05e7\u05d5\u05d1\u05e5 \u05d4swf.\ncontext-menu-copy-debug-info = \u05d4\u05e2\u05ea\u05e7\u05ea \u05e0\u05ea\u05d5\u05e0\u05d9 \u05e0\u05d9\u05e4\u05d5\u05d9 \u05e9\u05d2\u05d9\u05d0\u05d5\u05ea\ncontext-menu-open-save-manager = \u05e4\u05ea\u05d7 \u05d0\u05ea \u05de\u05e0\u05d4\u05dc \u05d4\u05e9\u05de\u05d9\u05e8\u05d5\u05ea\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] \u05d0\u05d5\u05d3\u05d5\u05ea \u05d4\u05ea\u05d5\u05e1\u05e3 Ruffle ({ $version })\n *[other] \u05d0\u05d5\u05d3\u05d5\u05ea Ruffle ({ $version })\n }\ncontext-menu-hide = \u05d4\u05e1\u05ea\u05e8 \u05ea\u05e4\u05e8\u05d9\u05d8 \u05d6\u05d4\ncontext-menu-exit-fullscreen = \u05d9\u05e6\u05d9\u05d0\u05d4 \u05de\u05de\u05e1\u05da \u05de\u05dc\u05d0\ncontext-menu-enter-fullscreen = \u05de\u05e1\u05da \u05de\u05dc\u05d0\ncontext-menu-volume-controls = \u05d1\u05e7\u05e8\u05ea \u05e2\u05d5\u05e6\u05de\u05ea \u05e7\u05d5\u05dc\n","messages.ftl":'message-cant-embed =\n Ruffle \u05dc\u05d0 \u05d4\u05e6\u05dc\u05d9\u05d7 \u05dc\u05d4\u05e8\u05d9\u05e5 \u05d0\u05ea \u05ea\u05d5\u05db\u05df \u05d4\u05e4\u05dc\u05d0\u05e9 \u05d4\u05de\u05d5\u05d8\u05de\u05e2 \u05d1\u05d3\u05e3 \u05d6\u05d4.\n \u05d0\u05ea\u05d4 \u05d9\u05db\u05d5\u05dc \u05dc\u05e4\u05ea\u05d5\u05d7 \u05d0\u05ea \u05d4\u05e7\u05d5\u05d1\u05e5 \u05d1\u05dc\u05e9\u05d5\u05e0\u05d9\u05ea \u05e0\u05e4\u05e8\u05d3\u05ea, \u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05e2\u05e7\u05d5\u05e3 \u05d1\u05e2\u05d9\u05d4 \u05d6\u05d5.\npanic-title = \u05de\u05e9\u05d4\u05d5 \u05d4\u05e9\u05ea\u05d1\u05e9 :(\nmore-info = \u05de\u05d9\u05d3\u05e2 \u05e0\u05d5\u05e1\u05e3\nrun-anyway = \u05d4\u05e4\u05e2\u05dc \u05d1\u05db\u05dc \u05d6\u05d0\u05ea\ncontinue = \u05d4\u05de\u05e9\u05da\nreport-bug = \u05d3\u05d5\u05d5\u05d7 \u05e2\u05dc \u05ea\u05e7\u05dc\u05d4\nupdate-ruffle = \u05e2\u05d3\u05db\u05df \u05d0\u05ea Ruffle\nruffle-demo = \u05d4\u05d3\u05d2\u05de\u05d4\nruffle-desktop = \u05d0\u05e4\u05dc\u05d9\u05e7\u05e6\u05d9\u05d9\u05ea \u05e9\u05d5\u05dc\u05d7\u05df \u05e2\u05d1\u05d5\u05d3\u05d4\nruffle-wiki = \u05e8\u05d0\u05d4 \u05d0\u05ea Ruffle wiki\nenable-hardware-acceleration = \u05e0\u05e8\u05d0\u05d4 \u05e9\u05d4\u05d0\u05e6\u05ea \u05d4\u05d7\u05d5\u05de\u05e8\u05d4 \u05e9\u05dc\u05da \u05dc\u05d0 \u05de\u05d5\u05e4\u05e2\u05dc\u05ea. \u05d1\u05e2\u05d5\u05d3 \u05e9\u05e8\u05d0\u05e4\u05dc \u05e2\u05e9\u05d5\u05d9 \u05dc\u05e2\u05d1\u05d5\u05d3, \u05d4\u05d5\u05d0 \u05d9\u05db\u05d5\u05dc \u05dc\u05d4\u05d9\u05d5\u05ea \u05d0\u05d9\u05d8\u05d9. \u05ea\u05d5\u05db\u05dc \u05dc\u05e8\u05d0\u05d5\u05ea \u05db\u05d9\u05e6\u05d3 \u05dc\u05d4\u05e4\u05e2\u05d9\u05dc \u05ea\u05db\u05d5\u05e0\u05d4 \u05d6\u05d5 \u05d1\u05dc\u05d7\u05d9\u05e6\u05d4 \u05e2\u05dc \u05d4\u05dc\u05d9\u05e0\u05e7 \u05d4\u05d6\u05d4.\nview-error-details = \u05e8\u05d0\u05d4 \u05e4\u05e8\u05d8\u05d9 \u05e9\u05d2\u05d9\u05d0\u05d4\nopen-in-new-tab = \u05e4\u05ea\u05d7 \u05d1\u05db\u05e8\u05d8\u05d9\u05e1\u05d9\u05d9\u05d4 \u05d7\u05d3\u05e9\u05d4\nclick-to-unmute = \u05dc\u05d7\u05e5 \u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05d1\u05d8\u05dc \u05d4\u05e9\u05ea\u05e7\u05d4\nerror-file-protocol =\n \u05e0\u05d3\u05de\u05d4 \u05e9\u05d0\u05ea\u05d4 \u05de\u05e8\u05d9\u05e5 \u05d0\u05ea Ruffle \u05ea\u05d7\u05ea \u05e4\u05e8\u05d5\u05d8\u05d5\u05e7\u05d5\u05dc "file:".\n \u05d6\u05d4 \u05dc\u05d0 \u05d9\u05e2\u05d1\u05d5\u05d3 \u05de\u05db\u05d9\u05d5\u05d5\u05df \u05e9\u05d3\u05e4\u05d3\u05e4\u05e0\u05d9\u05dd \u05d7\u05d5\u05e1\u05de\u05d9\u05dd \u05d0\u05e4\u05e9\u05e8\u05d5\u05d9\u05d5\u05ea \u05e8\u05d1\u05d5\u05ea \u05de\u05dc\u05e2\u05d1\u05d5\u05d3 \u05e2\u05e7\u05d1 \u05e1\u05d9\u05d1\u05d5\u05ea \u05d0\u05d1\u05d8\u05d7\u05d4.\n \u05d1\u05de\u05e7\u05d5\u05dd \u05d6\u05d4, \u05d0\u05e0\u05d5 \u05de\u05d6\u05de\u05d9\u05e0\u05d9\u05dd \u05d0\u05d5\u05ea\u05da \u05dc\u05d0\u05d7\u05e1\u05df \u05d0\u05ea\u05e8 \u05d6\u05d4 \u05ea\u05d7\u05ea \u05e9\u05e8\u05ea \u05de\u05e7\u05d5\u05de\u05d9 \u05d0\u05d5 \u05d4\u05d3\u05d2\u05de\u05d4 \u05d1\u05e8\u05e9\u05ea \u05d0\u05d5 \u05d3\u05e8\u05da \u05d0\u05e4\u05dc\u05d9\u05e7\u05e6\u05d9\u05d9\u05ea \u05e9\u05d5\u05dc\u05d7\u05df \u05d4\u05e2\u05d1\u05d5\u05d3\u05d4.\nerror-javascript-config =\n Ruffle \u05e0\u05ea\u05e7\u05dc \u05d1\u05ea\u05e7\u05dc\u05d4 \u05d7\u05de\u05d5\u05e8\u05d4 \u05e2\u05e7\u05d1 \u05d4\u05d2\u05d3\u05e8\u05ea JavaScript \u05e9\u05d2\u05d5\u05d9\u05d4.\n \u05d0\u05dd \u05d0\u05ea\u05d4 \u05de\u05e0\u05d4\u05dc \u05d4\u05d0\u05ea\u05e8, \u05d0\u05e0\u05d5 \u05de\u05d6\u05de\u05d9\u05e0\u05d9\u05dd \u05d0\u05d5\u05ea\u05da \u05dc\u05d1\u05d3\u05d5\u05e7 \u05d0\u05ea \u05e4\u05e8\u05d8\u05d9 \u05d4\u05e9\u05d2\u05d9\u05d0\u05d4 \u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05de\u05e6\u05d5\u05d0 \u05d0\u05d9\u05d6\u05d4 \u05e4\u05e8\u05de\u05d8\u05e8 \u05d4\u05d5\u05d0 \u05e9\u05d2\u05d5\u05d9.\n \u05d0\u05ea\u05d4 \u05d9\u05db\u05d5\u05dc \u05dc\u05e2\u05d9\u05d9\u05df \u05d5\u05dc\u05d4\u05d5\u05e2\u05e5 \u05d1wiki \u05e9\u05dc Ruffle \u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05e7\u05d1\u05dc \u05e2\u05d6\u05e8\u05d4.\nerror-wasm-not-found =\n Ruffle \u05e0\u05db\u05e9\u05dc \u05dc\u05d8\u05e2\u05d5\u05df \u05d0\u05ea \u05e7\u05d5\u05d1\u05e5 \u05d4"wasm." \u05d4\u05d3\u05e8\u05d5\u05e9.\n \u05d0\u05dd \u05d0\u05ea\u05d4 \u05de\u05e0\u05d4\u05dc \u05d4\u05d0\u05ea\u05e8, \u05d0\u05e0\u05d0 \u05d5\u05d5\u05d3\u05d0 \u05db\u05d9 \u05d4\u05e7\u05d5\u05d1\u05e5 \u05d4\u05d5\u05e2\u05dc\u05d4 \u05db\u05e9\u05d5\u05e8\u05d4.\n \u05d0\u05dd \u05d4\u05d1\u05e2\u05d9\u05d4 \u05de\u05de\u05e9\u05d9\u05db\u05d4, \u05d9\u05d9\u05ea\u05db\u05df \u05d5\u05ea\u05e6\u05d8\u05e8\u05da \u05dc\u05d4\u05e9\u05ea\u05de\u05e9 \u05d1\u05d4\u05d2\u05d3\u05e8\u05ea "publicPath": \u05d0\u05e0\u05d0 \u05e2\u05d9\u05d9\u05df \u05d5\u05d4\u05d5\u05e2\u05e5 \u05d1wiki \u05e9\u05dc Ruffle \u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05e7\u05d1\u05dc \u05e2\u05d6\u05e8\u05d4.\nerror-wasm-mime-type =\n Ruffle \u05e0\u05ea\u05e7\u05dc \u05d1\u05d1\u05e2\u05d9\u05d4 \u05d7\u05de\u05d5\u05e8\u05d4 \u05ea\u05d5\u05da \u05db\u05d3\u05d9 \u05e0\u05d9\u05e1\u05d9\u05d5\u05df \u05dc\u05d0\u05ea\u05d7\u05dc.\n \u05e9\u05e8\u05ea\u05d5 \u05e9\u05dc \u05d0\u05ea\u05e8 \u05d6\u05d4 \u05dc\u05d0 \u05de\u05e9\u05d9\u05d9\u05da \u05e7\u05d1\u05e6\u05d9 ".wasm" \u05e2\u05dd \u05e1\u05d5\u05d2 \u05d4MIME \u05d4\u05e0\u05db\u05d5\u05df.\n \u05d0\u05dd \u05d0\u05ea\u05d4 \u05de\u05e0\u05d4\u05dc \u05d4\u05d0\u05ea\u05e8, \u05d0\u05e0\u05d0 \u05e2\u05d9\u05d9\u05df \u05d5\u05d4\u05d5\u05e2\u05e5 \u05d1wiki \u05e9\u05dc Ruffle \u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05e7\u05d1\u05dc \u05e2\u05d6\u05e8\u05d4.\nerror-swf-fetch =\n Ruffle \u05e0\u05db\u05e9\u05dc \u05dc\u05d8\u05e2\u05d5\u05df \u05d0\u05ea \u05e7\u05d5\u05d1\u05e5 \u05d4\u05e4\u05dc\u05d0\u05e9/swf. .\n \u05d6\u05d4 \u05e0\u05d5\u05d1\u05e2 \u05db\u05db\u05dc \u05d4\u05e0\u05e8\u05d0\u05d4 \u05de\u05db\u05d9\u05d5\u05d5\u05df \u05d5\u05d4\u05e7\u05d5\u05d1\u05e5 \u05dc\u05d0 \u05e7\u05d9\u05d9\u05dd \u05d9\u05d5\u05ea\u05e8, \u05d0\u05d6 \u05d0\u05d9\u05df \u05dcRuffle \u05de\u05d4 \u05dc\u05d8\u05e2\u05d5\u05df.\n \u05e0\u05e1\u05d4 \u05dc\u05d9\u05e6\u05d5\u05e8 \u05e7\u05e9\u05e8 \u05e2\u05dd \u05de\u05e0\u05d4\u05dc \u05d4\u05d0\u05ea\u05e8 \u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05e7\u05d1\u05dc \u05e2\u05d6\u05e8\u05d4.\nerror-swf-cors =\n Ruffle \u05e0\u05db\u05e9\u05dc \u05dc\u05d8\u05e2\u05d5\u05df \u05d0\u05ea \u05e7\u05d5\u05d1\u05e5 \u05d4\u05e4\u05dc\u05d0\u05e9/swf. .\n \u05d2\u05d9\u05e9\u05d4 \u05dcfetch \u05db\u05db\u05dc \u05d4\u05e0\u05e8\u05d0\u05d4 \u05e0\u05d7\u05e1\u05de\u05d4 \u05e2\u05dc \u05d9\u05d3\u05d9 \u05de\u05d3\u05d9\u05e0\u05d9\u05d5\u05ea CORS.\n \u05d0\u05dd \u05d0\u05ea\u05d4 \u05de\u05e0\u05d4\u05dc \u05d4\u05d0\u05ea\u05e8, \u05d0\u05e0\u05d0 \u05e2\u05d9\u05d9\u05df \u05d5\u05d4\u05d5\u05e2\u05e5 \u05d1wiki \u05e9\u05dc Ruffle \u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05e7\u05d1\u05dc \u05e2\u05d6\u05e8\u05d4.\nerror-wasm-cors =\n Ruffle \u05e0\u05db\u05e9\u05dc \u05dc\u05d8\u05e2\u05d5\u05df \u05d0\u05ea \u05e7\u05d5\u05d1\u05e5 \u05d4".wasm" \u05d4\u05d3\u05e8\u05d5\u05e9.\n \u05d2\u05d9\u05e9\u05d4 \u05dcfetch \u05db\u05db\u05dc \u05d4\u05e0\u05e8\u05d0\u05d4 \u05e0\u05d7\u05e1\u05de\u05d4 \u05e2\u05dc \u05d9\u05d3\u05d9 \u05de\u05d3\u05d9\u05e0\u05d9\u05d5\u05ea CORS.\n \u05d0\u05dd \u05d0\u05ea\u05d4 \u05de\u05e0\u05d4\u05dc \u05d4\u05d0\u05ea\u05e8, \u05d0\u05e0\u05d0 \u05e2\u05d9\u05d9\u05df \u05d5\u05d4\u05d5\u05e2\u05e5 \u05d1wiki \u05e9\u05dc Ruffle \u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05e7\u05d1\u05dc \u05e2\u05d6\u05e8\u05d4.\nerror-wasm-invalid =\n Ruffle \u05e0\u05ea\u05e7\u05dc \u05d1\u05d1\u05e2\u05d9\u05d4 \u05d7\u05de\u05d5\u05e8\u05d4 \u05ea\u05d5\u05da \u05db\u05d3\u05d9 \u05e0\u05d9\u05e1\u05d9\u05d5\u05df \u05dc\u05d0\u05ea\u05d7\u05dc.\n \u05e0\u05d3\u05de\u05d4 \u05db\u05d9 \u05d1\u05d3\u05e3 \u05d6\u05d4 \u05d7\u05e1\u05e8\u05d9\u05dd \u05d0\u05d5 \u05dc\u05d0 \u05e2\u05d5\u05d1\u05d3\u05d9\u05dd \u05db\u05e8\u05d0\u05d5\u05d9 \u05e7\u05d1\u05e6\u05d9\u05dd \u05d0\u05e9\u05e8 \u05de\u05e9\u05de\u05e9\u05d9\u05dd \u05d0\u05ea Ruffle \u05db\u05d3\u05d9 \u05dc\u05e4\u05e2\u05d5\u05dc\n \u05d0\u05dd \u05d0\u05ea\u05d4 \u05de\u05e0\u05d4\u05dc \u05d4\u05d0\u05ea\u05e8, \u05d0\u05e0\u05d0 \u05e2\u05d9\u05d9\u05df \u05d5\u05d4\u05d5\u05e2\u05e5 \u05d1wiki \u05e9\u05dc Ruffle \u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05e7\u05d1\u05dc \u05e2\u05d6\u05e8\u05d4.\nerror-wasm-download =\n Ruffle \u05e0\u05ea\u05e7\u05dc \u05d1\u05d1\u05e2\u05d9\u05d4 \u05d7\u05de\u05d5\u05e8\u05d4 \u05ea\u05d5\u05da \u05db\u05d3\u05d9 \u05e0\u05d9\u05e1\u05d9\u05d5\u05df \u05dc\u05d0\u05ea\u05d7\u05dc.\n \u05dc\u05e2\u05d9\u05ea\u05d9\u05dd \u05d1\u05e2\u05d9\u05d4 \u05d6\u05d5 \u05d9\u05db\u05d5\u05dc\u05d4 \u05dc\u05e4\u05ea\u05d5\u05e8 \u05d0\u05ea \u05e2\u05e6\u05de\u05d4, \u05d0\u05d6 \u05d0\u05ea\u05d4 \u05d9\u05db\u05d5\u05dc \u05dc\u05e0\u05e1\u05d5\u05ea \u05dc\u05d8\u05e2\u05d5\u05df \u05de\u05d7\u05d3\u05e9 \u05d0\u05ea \u05d4\u05d3\u05e3 \u05d6\u05d4.\n \u05d0\u05dd \u05dc\u05d0, \u05d0\u05e0\u05d0 \u05e4\u05e0\u05d4 \u05dc\u05de\u05e0\u05d4\u05dc \u05d4\u05d0\u05ea\u05e8.\nerror-wasm-disabled-on-edge =\n Ruffle \u05e0\u05db\u05e9\u05dc \u05dc\u05d8\u05e2\u05d5\u05df \u05d0\u05ea \u05e7\u05d5\u05d1\u05e5 \u05d4".wasm" \u05d4\u05d3\u05e8\u05d5\u05e9.\n \u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05ea\u05e7\u05df \u05d1\u05e2\u05d9\u05d4 \u05d6\u05d5, \u05e0\u05e1\u05d4 \u05dc\u05e4\u05ea\u05d5\u05d7 \u05d0\u05ea \u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05d4\u05d3\u05e4\u05d3\u05e4\u05df \u05e9\u05dc\u05da, \u05dc\u05d7\u05e5 \u05e2\u05dc "\u05d0\u05d1\u05d8\u05d7\u05d4, \u05d7\u05d9\u05e4\u05d5\u05e9 \u05d5\u05e9\u05d9\u05e8\u05d5\u05ea",\n \u05d2\u05dc\u05d5\u05dc \u05de\u05d8\u05d4, \u05d5\u05db\u05d1\u05d4 \u05d0\u05ea "\u05d4\u05d2\u05d1\u05e8 \u05d0\u05ea \u05d4\u05d0\u05d1\u05d8\u05d7\u05d4 \u05e9\u05dc\u05da \u05d1\u05e8\u05e9\u05ea".\n \u05d6\u05d4 \u05d9\u05d0\u05e4\u05e9\u05e8 \u05dc\u05d3\u05e4\u05d3\u05e4\u05df \u05e9\u05dc\u05da \u05dc\u05d8\u05e2\u05d5\u05df \u05d0\u05ea \u05e7\u05d5\u05d1\u05e5 \u05d4".wasm" \u05d4\u05d3\u05e8\u05d5\u05e9.\n \u05d0\u05dd \u05d4\u05d1\u05e2\u05d9\u05d4 \u05de\u05de\u05e9\u05d9\u05db\u05d4, \u05d9\u05d9\u05ea\u05db\u05df \u05d5\u05e2\u05dc\u05d9\u05da \u05dc\u05d4\u05e9\u05ea\u05de\u05e9 \u05d1\u05d3\u05e4\u05d3\u05e4\u05df \u05d0\u05d7\u05e8.\nerror-javascript-conflict =\n Ruffle \u05e0\u05ea\u05e7\u05dc \u05d1\u05d1\u05e2\u05d9\u05d4 \u05d7\u05de\u05d5\u05e8\u05d4 \u05ea\u05d5\u05da \u05db\u05d3\u05d9 \u05e0\u05d9\u05e1\u05d9\u05d5\u05df \u05dc\u05d0\u05ea\u05d7\u05dc.\n \u05e0\u05d3\u05de\u05d4 \u05db\u05d9 \u05d3\u05e3 \u05d6\u05d4 \u05de\u05e9\u05ea\u05de\u05e9 \u05d1\u05e7\u05d5\u05d3 JavaScript \u05d0\u05e9\u05e8 \u05de\u05ea\u05e0\u05d2\u05e9 \u05e2\u05dd Ruffle.\n \u05d0\u05dd \u05d0\u05ea\u05d4 \u05de\u05e0\u05d4\u05dc \u05d4\u05d0\u05ea\u05e8, \u05d0\u05e0\u05d5 \u05de\u05d6\u05de\u05d9\u05e0\u05d9\u05dd \u05d0\u05d5\u05ea\u05da \u05dc\u05e0\u05e1\u05d5\u05ea \u05dc\u05d8\u05e2\u05d5\u05df \u05d0\u05ea \u05d4\u05d3\u05e3 \u05ea\u05d7\u05ea \u05e2\u05de\u05d5\u05d3 \u05e8\u05d9\u05e7.\nerror-javascript-conflict-outdated = \u05d1\u05e0\u05d5\u05e1\u05e3, \u05d0\u05ea\u05d4 \u05d9\u05db\u05d5\u05dc \u05dc\u05e0\u05e1\u05d5\u05ea \u05d5\u05dc\u05d4\u05e2\u05dc\u05d5\u05ea \u05d2\u05e8\u05e1\u05d0\u05d5\u05ea \u05e2\u05d3\u05db\u05e0\u05d9\u05d5\u05ea \u05e9\u05dc Ruffle \u05d0\u05e9\u05e8 \u05e2\u05dc\u05d5\u05dc\u05d9\u05dd \u05dc\u05e2\u05e7\u05d5\u05e3 \u05d1\u05e2\u05d9\u05d4 \u05d6\u05d5 (\u05d2\u05e8\u05e1\u05d4 \u05d6\u05d5 \u05d4\u05d9\u05e0\u05d4 \u05de\u05d9\u05d5\u05e9\u05e0\u05ea : { $buildDate }).\nerror-csp-conflict =\n Ruffle \u05e0\u05ea\u05e7\u05dc \u05d1\u05d1\u05e2\u05d9\u05d4 \u05d7\u05de\u05d5\u05e8\u05d4 \u05ea\u05d5\u05da \u05db\u05d3\u05d9 \u05e0\u05d9\u05e1\u05d9\u05d5\u05df \u05dc\u05d0\u05ea\u05d7\u05dc.\n \u05de\u05d3\u05d9\u05e0\u05d9\u05d5\u05ea \u05d0\u05d1\u05d8\u05d7\u05ea \u05d4\u05ea\u05d5\u05db\u05df \u05e9\u05dc \u05e9\u05e8\u05ea\u05d5 \u05e9\u05dc \u05d0\u05ea\u05e8 \u05d6\u05d4 \u05d0\u05d9\u05e0\u05d4 \u05de\u05d0\u05e4\u05e9\u05e8\u05ea \u05dc\u05e7\u05d5\u05d1\u05e5 \u05d4"wasm." \u05d4\u05d3\u05e8\u05d5\u05e9 \u05dc\u05e4\u05e2\u05d5\u05dc.\n \u05d0\u05dd \u05d0\u05ea\u05d4 \u05de\u05e0\u05d4\u05dc \u05d4\u05d0\u05ea\u05e8, \u05d0\u05e0\u05d0 \u05e2\u05d9\u05d9\u05df \u05d5\u05d4\u05d5\u05e2\u05e5 \u05d1wiki \u05e9\u05dc Ruffle \u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05e7\u05d1\u05dc \u05e2\u05d6\u05e8\u05d4.\nerror-unknown =\n Ruffle \u05e0\u05ea\u05e7\u05dc \u05d1\u05d1\u05e2\u05d9\u05d4 \u05d7\u05de\u05d5\u05e8\u05d4 \u05d1\u05e0\u05d9\u05e1\u05d9\u05d5\u05df \u05dc\u05d4\u05e6\u05d9\u05d2 \u05d0\u05ea \u05ea\u05d5\u05db\u05df \u05e4\u05dc\u05d0\u05e9 \u05d6\u05d4.\n { $outdated ->\n [true] \u05d0\u05dd \u05d0\u05ea\u05d4 \u05de\u05e0\u05d4\u05dc \u05d4\u05d0\u05ea\u05e8, \u05d0\u05e0\u05d0 \u05e0\u05e1\u05d4 \u05dc\u05d4\u05e2\u05dc\u05d5\u05ea \u05d2\u05e8\u05e1\u05d4 \u05e2\u05d3\u05db\u05e0\u05d9\u05ea \u05d9\u05d5\u05ea\u05e8 \u05e9\u05dc Ruffle (\u05d2\u05e8\u05e1\u05d4 \u05d6\u05d5 \u05d4\u05d9\u05e0\u05d4 \u05de\u05d9\u05d5\u05e9\u05e0\u05ea: { $buildDate }).\n *[false] \u05d6\u05d4 \u05dc\u05d0 \u05d0\u05de\u05d5\u05e8 \u05dc\u05e7\u05e8\u05d5\u05ea, \u05e0\u05e9\u05de\u05d7 \u05d0\u05dd \u05ea\u05d5\u05db\u05dc \u05dc\u05e9\u05ea\u05e3 \u05ea\u05e7\u05dc\u05d4 \u05d6\u05d5!\n }\n',"save-manager.ftl":"save-delete-prompt = \u05d4\u05d0\u05dd \u05d0\u05ea\u05d4 \u05d1\u05d8\u05d5\u05d7 \u05e9\u05d1\u05e8\u05e6\u05d5\u05e0\u05da \u05dc\u05de\u05d7\u05d5\u05e7 \u05d0\u05ea \u05e7\u05d5\u05d1\u05e5 \u05e9\u05de\u05d9\u05e8\u05d4 \u05d6\u05d4?\nsave-reload-prompt =\n \u05d4\u05d3\u05e8\u05da \u05d4\u05d9\u05d7\u05d9\u05d3\u05d4 { $action ->\n [delete] \u05dc\u05de\u05d7\u05d5\u05e7\n *[replace] \u05dc\u05d4\u05d7\u05dc\u05d9\u05e3\n } \u05d0\u05ea \u05e7\u05d5\u05d1\u05e5 \u05d4\u05e9\u05de\u05d9\u05e8\u05d4 \u05d4\u05d6\u05d4 \u05de\u05d1\u05dc\u05d9 \u05dc\u05d2\u05e8\u05d5\u05dd \u05dc\u05d5 \u05dc\u05d4\u05ea\u05e0\u05d2\u05e9 \u05d4\u05d9\u05d0 \u05dc\u05d8\u05e2\u05d5\u05df \u05de\u05d7\u05d3\u05e9 \u05d0\u05ea \u05ea\u05d5\u05db\u05df \u05d6\u05d4. \u05d4\u05d0\u05dd \u05d0\u05ea\u05d4 \u05e8\u05d5\u05e6\u05d4 \u05dc\u05d4\u05de\u05e9\u05d9\u05da \u05d1\u05db\u05dc \u05d6\u05d0\u05ea?\nsave-download = \u05d4\u05d5\u05e8\u05d3\u05d4\nsave-replace = \u05d4\u05d7\u05dc\u05e4\u05d4\nsave-delete = \u05de\u05d7\u05d9\u05e7\u05d4\nsave-backup-all = \u05d4\u05d5\u05e8\u05d3\u05ea \u05db\u05dc \u05e7\u05d1\u05e6\u05d9 \u05d4\u05e9\u05de\u05d9\u05e8\u05d4\n","volume-controls.ftl":"volume-controls = \u05d1\u05e7\u05e8\u05ea \u05e2\u05d5\u05e6\u05de\u05ea \u05e7\u05d5\u05dc\nvolume-controls-mute = \u05d4\u05e9\u05ea\u05e7\nvolume-controls-volume = \u05e2\u05d5\u05e6\u05de\u05ea \u05e7\u05d5\u05dc\n"},"hu-HU":{"context_menu.ftl":"context-menu-download-swf = .swf f\xe1jl let\xf6lt\xe9se\ncontext-menu-copy-debug-info = Hibakeres\xe9si inform\xe1ci\xf3k m\xe1sol\xe1sa\ncontext-menu-open-save-manager = Ment\xe9skezel\u0151 megnyit\xe1sa\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] A Ruffle kieg\xe9sz\xedt\u0151 ({ $version }) n\xe9vjegye\n *[other] A Ruffle ({ $version }) n\xe9vjegye\n }\ncontext-menu-hide = Ezen men\xfc elrejt\xe9se\ncontext-menu-exit-fullscreen = Kil\xe9p\xe9s a teljes k\xe9perny\u0151b\u0151l\ncontext-menu-enter-fullscreen = V\xe1lt\xe1s teljes k\xe9perny\u0151re\ncontext-menu-volume-controls = Hanger\u0151szab\xe1lyz\xf3\n","messages.ftl":'message-cant-embed =\n A Ruffle nem tudta futtatni az oldalba \xe1gyazott Flash tartalmat.\n A probl\xe9ma kiker\xfcl\xe9s\xe9hez megpr\xf3b\xe1lhatod megnyitni a f\xe1jlt egy k\xfcl\xf6n lapon.\npanic-title = Valami baj t\xf6rt\xe9nt :(\nmore-info = Tov\xe1bbi inform\xe1ci\xf3\nrun-anyway = Futtat\xe1s m\xe9gis\ncontinue = Folytat\xe1s\nreport-bug = Hiba jelent\xe9se\nupdate-ruffle = Ruffle friss\xedt\xe9se\nruffle-demo = Webes dem\xf3\nruffle-desktop = Asztali alkalmaz\xe1s\nruffle-wiki = Ruffle Wiki megnyit\xe1sa\nenable-hardware-acceleration = \xdagy t\u0171nik, a hardveres gyors\xedt\xe1s nincs enged\xe9lyezve. B\xe1r a Ruffle m\u0171k\xf6dhet, nagyon lass\xfa lehet. Ezt a hivatkoz\xe1st k\xf6vetve megtudhatod, hogyan enged\xe9lyezd a hardveres gyors\xedt\xe1st.\nview-error-details = Hiba r\xe9szletei\nopen-in-new-tab = Megnyit\xe1s \xfaj lapon\nclick-to-unmute = Kattints a n\xe9m\xedt\xe1s felold\xe1s\xe1hoz\nerror-file-protocol =\n \xdagy t\u0171nik, a Ruffle-t a "file:" protokollon futtatod.\n Ez nem m\u0171k\xf6dik, mivel \xedgy a b\xf6ng\xe9sz\u0151k biztons\xe1gi okokb\xf3l sz\xe1mos funkci\xf3 m\u0171k\xf6d\xe9s\xe9t letiltj\xe1k.\n Ehelyett azt aj\xe1nljuk hogy ind\xedts egy helyi kiszolg\xe1l\xf3t, vagy haszn\xe1ld a webes dem\xf3t vagy az asztali alkalmaz\xe1st.\nerror-javascript-config =\n A Ruffle komoly probl\xe9m\xe1ba \xfctk\xf6z\xf6tt egy helytelen JavaScript-konfigur\xe1ci\xf3 miatt.\n Ha a szerver rendszergazd\xe1ja vagy, k\xe9rj\xfck, ellen\u0151rizd a hiba r\xe9szleteit, hogy megtudd, melyik param\xe9ter a hib\xe1s.\n A Ruffle wikiben is tal\xe1lhatsz ehhez seg\xedts\xe9get.\nerror-wasm-not-found =\n A Ruffle nem tudta bet\xf6lteni a sz\xfcks\xe9ges ".wasm" \xf6sszetev\u0151t.\n Ha a szerver rendszergazd\xe1ja vagy, k\xe9rj\xfck ellen\u0151rizd, hogy a f\xe1jl megfelel\u0151en lett-e felt\xf6ltve.\n Ha a probl\xe9ma tov\xe1bbra is fenn\xe1ll, el\u0151fordulhat, hogy a "publicPath" be\xe1ll\xedt\xe1st kell haszn\xe1lnod: seg\xedts\xe9g\xe9rt keresd fel a Ruffle wikit.\nerror-wasm-mime-type =\n A Ruffle komoly probl\xe9m\xe1ba \xfctk\xf6z\xf6tt az inicializ\xe1l\xe1s sor\xe1n.\n Ez a webszerver a ".wasm" f\xe1jlokat nem a megfelel\u0151 MIME-t\xedpussal szolg\xe1lja ki.\n Ha a szerver rendszergazd\xe1ja vagy, k\xe9rj\xfck, keresd fel a Ruffle wikit seg\xedts\xe9g\xe9rt.\nerror-swf-fetch =\n A Ruffle nem tudta bet\xf6lteni a Flash SWF f\xe1jlt.\n A legval\xf3sz\xedn\u0171bb ok az, hogy a f\xe1jl m\xe1r nem l\xe9tezik, \xedgy a Ruffle sz\xe1m\xe1ra nincs mit bet\xf6lteni.\n Pr\xf3b\xe1ld meg felvenni a kapcsolatot a webhely rendszergazd\xe1j\xe1val seg\xedts\xe9g\xe9rt.\nerror-swf-cors =\n A Ruffle nem tudta bet\xf6lteni a Flash SWF f\xe1jlt.\n A lek\xe9r\xe9shez val\xf3 hozz\xe1f\xe9r\xe9st val\xf3sz\xedn\u0171leg letiltotta a CORS-h\xe1zirend.\n Ha a szerver rendszergazd\xe1ja vagy, k\xe9rj\xfck, keresd fel a Ruffle wikit seg\xedts\xe9g\xe9rt.\nerror-wasm-cors =\n A Ruffle nem tudta bet\xf6lteni a sz\xfcks\xe9ges ".wasm" \xf6sszetev\u0151t.\n A lek\xe9r\xe9shez val\xf3 hozz\xe1f\xe9r\xe9st val\xf3sz\xedn\u0171leg letiltotta a CORS-h\xe1zirend.\n Ha a szerver rendszergazd\xe1ja vagy, k\xe9rj\xfck keresd fel a Ruffle wikit seg\xedts\xe9g\xe9rt.\nerror-wasm-invalid =\n A Ruffle komoly probl\xe9m\xe1ba \xfctk\xf6z\xf6tt az inicializ\xe1l\xe1s sor\xe1n.\n \xdagy t\u0171nik, hogy ezen az oldalon hi\xe1nyoznak vagy hib\xe1sak a Ruffle futtat\xe1s\xe1hoz sz\xfcks\xe9ges f\xe1jlok.\n Ha a szerver rendszergazd\xe1ja vagy, k\xe9rj\xfck keresd fel a Ruffle wikit seg\xedts\xe9g\xe9rt.\nerror-wasm-download =\n A Ruffle komoly probl\xe9m\xe1ba \xfctk\xf6z\xf6tt az inicializ\xe1l\xe1s sor\xe1n.\n Ez gyakran mag\xe1t\xf3l megold\xf3dik, ez\xe9rt megpr\xf3b\xe1lhatod \xfajrat\xf6lteni az oldalt.\n Ellenkez\u0151 esetben fordulj a webhely rendszergazd\xe1j\xe1hoz.\nerror-wasm-disabled-on-edge =\n A Ruffle nem tudta bet\xf6lteni a sz\xfcks\xe9ges ".wasm" \xf6sszetev\u0151t.\n A probl\xe9ma megold\xe1s\xe1hoz nyisd meg a b\xf6ng\xe9sz\u0151 be\xe1ll\xedt\xe1sait, kattints az \u201eAdatv\xe9delem, keres\xe9s \xe9s szolg\xe1ltat\xe1sok\u201d elemre, g\xf6rgess le, \xe9s kapcsold ki a \u201eFokozott biztons\xe1g a weben\u201d opci\xf3t.\n Ez lehet\u0151v\xe9 teszi a b\xf6ng\xe9sz\u0151 sz\xe1m\xe1ra, hogy bet\xf6ltse a sz\xfcks\xe9ges ".wasm" f\xe1jlokat.\n Ha a probl\xe9ma tov\xe1bbra is fenn\xe1ll, lehet, hogy m\xe1sik b\xf6ng\xe9sz\u0151t kell haszn\xe1lnod.\nerror-javascript-conflict =\n A Ruffle komoly probl\xe9m\xe1ba \xfctk\xf6z\xf6tt az inicializ\xe1l\xe1s sor\xe1n.\n \xdagy t\u0171nik, ez az oldal olyan JavaScript-k\xf3dot haszn\xe1l, amely \xfctk\xf6zik a Ruffle-lel.\n Ha a kiszolg\xe1l\xf3 rendszergazd\xe1ja vagy, k\xe9rj\xfck, pr\xf3b\xe1ld meg a f\xe1jlt egy \xfcres oldalon bet\xf6lteni.\nerror-javascript-conflict-outdated = Megpr\xf3b\xe1lhatod tov\xe1bb\xe1 felt\xf6lteni a Ruffle egy \xfajabb verzi\xf3j\xe1t is, amely megker\xfclheti a probl\xe9m\xe1t (a jelenlegi elavult: { $buildDate }).\nerror-csp-conflict =\n A Ruffle komoly probl\xe9m\xe1ba \xfctk\xf6z\xf6tt az inicializ\xe1l\xe1s sor\xe1n.\n A kiszolg\xe1l\xf3 tartalombiztons\xe1gi h\xe1zirendje nem teszi lehet\u0151v\xe9 a sz\xfcks\xe9ges \u201e.wasm\u201d \xf6sszetev\u0151k futtat\xe1s\xe1t.\n Ha a szerver rendszergazd\xe1ja vagy, k\xe9rj\xfck, keresd fel a Ruffle wikit seg\xedts\xe9g\xe9rt.\nerror-unknown =\n A Ruffle komoly probl\xe9m\xe1ba \xfctk\xf6z\xf6tt, mik\xf6zben megpr\xf3b\xe1lta megjelen\xedteni ezt a Flash-tartalmat.\n { $outdated ->\n [true] Ha a szerver rendszergazd\xe1ja vagy, k\xe9rj\xfck, pr\xf3b\xe1ld meg felt\xf6lteni a Ruffle egy \xfajabb verzi\xf3j\xe1t (a jelenlegi elavult: { $buildDate }).\n *[false] Ennek nem lett volna szabad megt\xf6rt\xe9nnie, ez\xe9rt nagyon h\xe1l\xe1sak lenn\xe9nk, ha jelezn\xe9d a hib\xe1t!\n }\n',"save-manager.ftl":"save-delete-prompt = Biztosan t\xf6r\xf6lni akarod ezt a ment\xe9st?\nsave-reload-prompt =\n Ennek a ment\xe9snek az esetleges konfliktus n\xe9lk\xfcli { $action ->\n [delete] t\xf6rl\xe9s\xe9hez\n *[replace] cser\xe9j\xe9hez\n } \xfajra kell t\xf6lteni a tartalmat. M\xe9gis szeretn\xe9d folytatni?\nsave-download = Let\xf6lt\xe9s\nsave-replace = Csere\nsave-delete = T\xf6rl\xe9s\nsave-backup-all = Az \xf6sszes f\xe1jl let\xf6lt\xe9se\n","volume-controls.ftl":"volume-controls = Hanger\u0151szab\xe1lyz\xf3\nvolume-controls-mute = N\xe9m\xedt\xe1s\nvolume-controls-volume = Hanger\u0151\n"},"id-ID":{"context_menu.ftl":"context-menu-download-swf = Unduh .swf\ncontext-menu-copy-debug-info = Salin info debug\ncontext-menu-open-save-manager = Buka Manager Save\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] Tentang Ekstensi Ruffle ({ $version })\n *[other] Tentang Ruffle ({ $version })\n }\ncontext-menu-hide = Sembunyikan Menu ini\ncontext-menu-exit-fullscreen = Keluar dari layar penuh\ncontext-menu-enter-fullscreen = Masuk mode layar penuh\ncontext-menu-volume-controls = Pengaturan Volume\n","messages.ftl":'message-cant-embed =\n Ruffle tidak dapat menjalankan Flash yang disematkan di halaman ini.\n Anda dapat mencoba membuka file di tab terpisah, untuk menghindari masalah ini.\npanic-title = Terjadi kesalahan :(\nmore-info = Info lebih lanjut\nrun-anyway = Jalankan\ncontinue = Lanjutkan\nreport-bug = Laporkan Bug\nupdate-ruffle = Perbarui Ruffle\nruffle-demo = Demo Web\nruffle-desktop = Aplikasi Desktop\nruffle-wiki = Kunjungi Wiki Ruffle\nenable-hardware-acceleration = Sepertinya akselerasi perangkat keras tidak aktif. Ruffle tetap akan bekerja, Namun dapat bekerja dengan sangat lambat. Anda dapat mengaktifkan akselerasi perangkat keras dengan menggunakan link berikut.\nview-error-details = Tunjukan Detail Error\nopen-in-new-tab = Buka di Tab Baru\nclick-to-unmute = Tekan untuk menyalakan suara\nerror-file-protocol =\n Sepertinya anda menjalankan Ruffle di protokol "file:". \n Ini tidak berfungsi karena browser memblokir fitur ini dengan alasan keamanan.\n Sebagai gantinya, kami mengajak anda untuk membuat server lokal, menggunakan demo web atau aplikasi desktop.\nerror-javascript-config =\n Ruffle mengalami masalah besar karena konfigurasi JavaScript yang salah.\n Jika Anda adalah administrator server ini, kami mengajak Anda untuk memeriksa detail kesalahan untuk mengetahui parameter mana yang salah.\n Anda juga dapat membaca wiki Ruffle untuk mendapatkan bantuan.\nerror-wasm-not-found =\n Ruffle gagal memuat komponen file ".wasm" yang diperlukan.\n Jika Anda adalah administrator server ini, pastikan file telah diunggah dengan benar.\n Jika masalah terus berlanjut, Anda mungkin perlu menggunakan pengaturan "publicPath": silakan baca wiki Ruffle untuk mendapatkan bantuan.\nerror-wasm-mime-type =\n Ruffle mengalami masalah ketika mencoba melakukan inisialisasi.\n Server web ini tidak melayani file ".wasm" dengan tipe MIME yang benar.\n Jika Anda adalah administrator server ini, silakan baca wiki Ruffle untuk mendapatkan bantuan.\nerror-swf-fetch =\n Ruffle gagal memuat file SWF Flash.\n Kemungkinan file tersebut sudah tidak ada, sehingga tidak dapat dimuat oleh Ruffle.\n Coba hubungi administrator situs web ini untuk mendapatkan bantuan.\nerror-swf-cors =\n Ruffle gagal memuat file SWF Flash.\n Akses untuk memuat kemungkinan telah diblokir oleh kebijakan CORS.\n Jika Anda adalah administrator server ini, silakan baca wiki Ruffle untuk mendapatkan bantuan.\nerror-wasm-cors =\n Ruffle gagal memuat komponen file ".wasm" yang diperlukan.\n Akses untuk mengambil kemungkinan telah diblokir oleh kebijakan CORS.\n Jika Anda adalah administrator server ini, silakan baca wiki Ruffle untuk mendapatkan bantuan.\nerror-wasm-invalid =\n Ruffle mengalami masalah besar ketika mencoba melakukan inisialisasi.\n Sepertinya halaman ini memiliki file yang hilang atau tidak valid untuk menjalankan Ruffle.\n Jika Anda adalah administrator server ini, silakan baca wiki Ruffle untuk mendapatkan bantuan.\nerror-wasm-download =\n Ruffle mengalami masalah besar ketika mencoba melakukan inisialisasi.\n Hal ini sering kali dapat teratasi dengan sendirinya, sehingga Anda dapat mencoba memuat ulang halaman.\n Jika tidak, silakan hubungi administrator situs web ini.\nerror-wasm-disabled-on-edge =\n Ruffle gagal memuat komponen file ".wasm" yang diperlukan.\n Untuk mengatasinya, coba buka pengaturan peramban Anda, klik "Privasi, pencarian, dan layanan", turun ke bawah, dan matikan "Tingkatkan keamanan Anda di web".\n Ini akan memungkinkan browser Anda memuat file ".wasm" yang diperlukan.\n Jika masalah berlanjut, Anda mungkin harus menggunakan browser yang berbeda.\nerror-javascript-conflict =\n Ruffle mengalami masalah besar ketika mencoba melakukan inisialisasi.\n Sepertinya situs web ini menggunakan kode JavaScript yang bertentangan dengan Ruffle.\n Jika Anda adalah administrator server ini, kami mengajak Anda untuk mencoba memuat file pada halaman kosong.\nerror-javascript-conflict-outdated = Anda juga dapat mencoba mengunggah versi Ruffle yang lebih baru yang mungkin dapat mengatasi masalah ini (versi saat ini sudah kedaluwarsa: { $buildDate }).\nerror-csp-conflict =\n Ruffle mengalami masalah besar ketika mencoba melakukan inisialisasi.\n Kebijakan Keamanan Konten server web ini tidak mengizinkan komponen ".wasm" yang diperlukan untuk dijalankan.\n Jika Anda adalah administrator server ini, silakan baca wiki Ruffle untuk mendapatkan bantuan.\nerror-unknown =\n Ruffle telah mengalami masalah besar saat menampilkan konten Flash ini.\n { $outdated ->\n [true] Jika Anda administrator server ini, cobalah untuk mengganti versi Ruffle yang lebih baru (versi saat ini sudah kedaluwarsa: { $buildDate }).\n *[false] Hal ini seharusnya tidak terjadi, jadi kami sangat menghargai jika Anda dapat melaporkan bug ini!\n }\n',"save-manager.ftl":"save-delete-prompt = Anda yakin ingin menghapus berkas ini?\nsave-reload-prompt =\n Satu-satunya cara untuk { $action ->\n [delete] menghapus\n *[replace] mengganti\n } berkas penyimpanan ini tanpa potensi konflik adalah dengan memuat ulang konten ini. Apakah Anda ingin melanjutkannya?\nsave-download = Unduh\nsave-replace = Ganti\nsave-delete = Hapus\nsave-backup-all = Unduh semua berkas penyimpanan\n","volume-controls.ftl":"volume-controls = Pengaturan Volume\nvolume-controls-mute = Bisukan\nvolume-controls-volume = Volume\n"},"it-IT":{"context_menu.ftl":"context-menu-download-swf = Scarica .swf\ncontext-menu-copy-debug-info = Copia informazioni di debug\ncontext-menu-open-save-manager = Apri Gestione salvataggi\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] Informazioni su Ruffle Extension ({ $version })\n *[other] Informazioni su Ruffle ({ $version })\n }\ncontext-menu-hide = Nascondi questo menu\ncontext-menu-exit-fullscreen = Esci dallo schermo intero\ncontext-menu-enter-fullscreen = Entra a schermo intero\ncontext-menu-volume-controls = Controlli volume\n","messages.ftl":"message-cant-embed =\n Ruffle non \xe8 stato in grado di eseguire il Flash incorporato in questa pagina.\n Puoi provare ad aprire il file in una scheda separata, per evitare questo problema.\npanic-title = Qualcosa \xe8 andato storto :(\nmore-info = Maggiori informazioni\nrun-anyway = Esegui comunque\ncontinue = Continua\nreport-bug = Segnala Un Bug\nupdate-ruffle = Aggiorna Ruffle\nruffle-demo = Demo Web\nruffle-desktop = Applicazione Desktop\nruffle-wiki = Visualizza Ruffle Wiki\nenable-hardware-acceleration = Sembra che l'accelerazione hardware non sia abilitata. Sebbene Ruffle possa funzionare, potrebbe essere irragionevolmente lento. Puoi scoprire come abilitare l'accelerazione hardware seguendo questo collegamento.\nview-error-details = Visualizza Dettagli Errore\nopen-in-new-tab = Apri in una nuova scheda\nclick-to-unmute = Clicca per riattivare l'audio\nerror-file-protocol =\n Sembra che tu stia eseguendo Ruffle sul protocollo \"file:\".\n Questo non funziona come browser blocca molte funzionalit\xe0 di lavoro per motivi di sicurezza.\n Invece, ti invitiamo a configurare un server locale o a utilizzare la demo web o l'applicazione desktop.\nerror-javascript-config =\n Ruffle ha incontrato un problema importante a causa di una configurazione JavaScript non corretta.\n Se sei l'amministratore del server, ti invitiamo a controllare i dettagli dell'errore per scoprire quale parametro \xe8 in errore.\n Puoi anche consultare il wiki Ruffle per aiuto.\nerror-wasm-not-found =\n Ruffle non \xe8 riuscito a caricare il componente di file \".wasm\".\n Se sei l'amministratore del server, assicurati che il file sia stato caricato correttamente.\n Se il problema persiste, potrebbe essere necessario utilizzare l'impostazione \"publicPath\": si prega di consultare il wiki Ruffle per aiuto.\nerror-wasm-mime-type =\n Ruffle ha incontrato un problema importante durante il tentativo di inizializzazione.\n Questo server web non serve \". asm\" file con il tipo MIME corretto.\n Se sei l'amministratore del server, consulta la wiki Ruffle per aiuto.\nerror-swf-fetch =\n Ruffle non \xe8 riuscito a caricare il file Flash SWF.\n La ragione pi\xf9 probabile \xe8 che il file non esiste pi\xf9, quindi non c'\xe8 nulla che Ruffle possa caricare.\n Prova a contattare l'amministratore del sito web per aiuto.\nerror-swf-cors =\n Ruffle non \xe8 riuscito a caricare il file SWF Flash.\n L'accesso al recupero probabilmente \xe8 stato bloccato dalla politica CORS.\n Se sei l'amministratore del server, consulta la wiki Ruffle per ricevere aiuto.\nerror-wasm-cors =\n Ruffle non \xe8 riuscito a caricare il componente di file \".wasm\".\n L'accesso al recupero probabilmente \xe8 stato bloccato dalla politica CORS.\n Se sei l'amministratore del server, consulta la wiki Ruffle per ricevere aiuto.\nerror-wasm-invalid =\n Ruffle ha incontrato un problema importante durante il tentativo di inizializzazione.\n Sembra che questa pagina abbia file mancanti o non validi per l'esecuzione di Ruffle.\n Se sei l'amministratore del server, consulta la wiki Ruffle per ricevere aiuto.\nerror-wasm-download =\n Ruffle ha incontrato un problema importante durante il tentativo di inizializzazione.\n Questo pu\xf2 spesso risolversi da solo, quindi puoi provare a ricaricare la pagina.\n Altrimenti, contatta l'amministratore del sito.\nerror-wasm-disabled-on-edge =\n Ruffle non ha caricato il componente di file \".wasm\" richiesto.\n Per risolvere il problema, prova ad aprire le impostazioni del tuo browser, facendo clic su \"Privacy, search, and services\", scorrendo verso il basso e disattivando \"Migliora la tua sicurezza sul web\".\n Questo permetter\xe0 al tuo browser di caricare i file \".wasm\" richiesti.\n Se il problema persiste, potresti dover usare un browser diverso.\nerror-javascript-conflict =\n Ruffle ha riscontrato un problema importante durante il tentativo di inizializzazione.\n Sembra che questa pagina utilizzi il codice JavaScript che \xe8 in conflitto con Ruffle.\n Se sei l'amministratore del server, ti invitiamo a provare a caricare il file su una pagina vuota.\nerror-javascript-conflict-outdated = Puoi anche provare a caricare una versione pi\xf9 recente di Ruffle che potrebbe aggirare il problema (l'attuale build \xe8 obsoleta: { $buildDate }).\nerror-csp-conflict =\n Ruffle ha incontrato un problema importante durante il tentativo di inizializzare.\n La Politica di Sicurezza dei Contenuti di questo server web non consente l'impostazione richiesta\". asm\" componente da eseguire.\n Se sei l'amministratore del server, consulta la Ruffle wiki per aiuto.\nerror-unknown =\n Ruffle ha incontrato un problema importante durante il tentativo di visualizzare questo contenuto Flash.\n { $outdated ->\n [true] Se sei l'amministratore del server, prova a caricare una versione pi\xf9 recente di Ruffle (la versione attuale \xe8 obsoleta: { $buildDate }).\n *[false] Questo non dovrebbe accadere, quindi ci piacerebbe molto se si potesse inviare un bug!\n }\n","save-manager.ftl":"save-delete-prompt = Sei sicuro di voler eliminare questo file di salvataggio?\nsave-reload-prompt =\n L'unico modo per { $action ->\n [delete] delete\n *[replace] replace\n } questo salvataggio file senza potenziali conflitti \xe8 quello di ricaricare questo contenuto. Volete continuare comunque?\nsave-download = Scarica\nsave-replace = Sostituisci\nsave-delete = Elimina\nsave-backup-all = Scarica tutti i file di salvataggio\n","volume-controls.ftl":"volume-controls = Controlli volume\nvolume-controls-mute = Silenzia\nvolume-controls-volume = Volume\n"},"ja-JP":{"context_menu.ftl":"context-menu-download-swf = .swf\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\ncontext-menu-copy-debug-info = \u30c7\u30d0\u30c3\u30b0\u60c5\u5831\u3092\u30b3\u30d4\u30fc\ncontext-menu-open-save-manager = \u30bb\u30fc\u30d6\u30de\u30cd\u30fc\u30b8\u30e3\u30fc\u3092\u958b\u304f\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] Ruffle\u62e1\u5f35\u6a5f\u80fd\u306b\u3064\u3044\u3066 ({ $version })\n *[other] Ruffle\u306b\u3064\u3044\u3066 ({ $version })\n }\ncontext-menu-hide = \u30e1\u30cb\u30e5\u30fc\u3092\u96a0\u3059\ncontext-menu-exit-fullscreen = \u30d5\u30eb\u30b9\u30af\u30ea\u30fc\u30f3\u3092\u7d42\u4e86\ncontext-menu-enter-fullscreen = \u30d5\u30eb\u30b9\u30af\u30ea\u30fc\u30f3\u306b\u3059\u308b\ncontext-menu-volume-controls = \u97f3\u91cf\n","messages.ftl":'message-cant-embed =\n Ruffle\u306f\u3053\u306e\u30da\u30fc\u30b8\u306b\u57cb\u3081\u8fbc\u307e\u308c\u305f Flash \u3092\u5b9f\u884c\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\n \u5225\u306e\u30bf\u30d6\u3067\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u304f\u3053\u3068\u3067\u3001\u3053\u306e\u554f\u984c\u3092\u89e3\u6c7a\u3067\u304d\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002\npanic-title = \u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f :(\nmore-info = \u8a73\u7d30\u60c5\u5831\nrun-anyway = \u3068\u306b\u304b\u304f\u5b9f\u884c\u3059\u308b\ncontinue = \u7d9a\u884c\nreport-bug = \u30d0\u30b0\u3092\u5831\u544a\nupdate-ruffle = Ruffle\u3092\u66f4\u65b0\nruffle-demo = Web\u30c7\u30e2\nruffle-desktop = \u30c7\u30b9\u30af\u30c8\u30c3\u30d7\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\nruffle-wiki = Ruffle Wiki\u3092\u8868\u793a\nenable-hardware-acceleration = \u30cf\u30fc\u30c9\u30a6\u30a7\u30a2\u30a2\u30af\u30bb\u30e9\u30ec\u30fc\u30b7\u30e7\u30f3\u304c\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u306a\u3044\u3088\u3046\u3067\u3059\u3002Ruffle\u304c\u52d5\u4f5c\u3057\u306a\u3044\u304b\u3001\u52d5\u4f5c\u304c\u9045\u304f\u306a\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 \u30cf\u30fc\u30c9\u30a6\u30a7\u30a2\u30a2\u30af\u30bb\u30e9\u30ec\u30fc\u30b7\u30e7\u30f3\u3092\u6709\u52b9\u306b\u3059\u308b\u65b9\u6cd5\u306b\u3064\u3044\u3066\u306f\u3001\u3053\u3061\u3089\u306e\u30ea\u30f3\u30af\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002\nview-error-details = \u30a8\u30e9\u30fc\u306e\u8a73\u7d30\u3092\u8868\u793a\nopen-in-new-tab = \u65b0\u3057\u3044\u30bf\u30d6\u3067\u958b\u304f\nclick-to-unmute = \u30af\u30ea\u30c3\u30af\u3067\u30df\u30e5\u30fc\u30c8\u3092\u89e3\u9664\nerror-file-protocol =\n Ruffle\u3092"file:"\u30d7\u30ed\u30c8\u30b3\u30eb\u3067\u4f7f\u7528\u3057\u3066\u3044\u308b\u3088\u3046\u3067\u3059\u3002\n \u30d6\u30e9\u30a6\u30b6\u306f\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u4e0a\u306e\u7406\u7531\u304b\u3089\u6b86\u3069\u306e\u6a5f\u80fd\u3092\u5236\u9650\u3057\u3066\u3044\u308b\u305f\u3081\u3001\u6b63\u3057\u304f\u52d5\u4f5c\u3057\u307e\u305b\u3093\u3002\n \u30ed\u30fc\u30ab\u30eb\u30b5\u30fc\u30d0\u30fc\u3092\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u3059\u308b\u304b\u3001\u30a6\u30a7\u30d6\u30c7\u30e2\u307e\u305f\u306f\u30c7\u30b9\u30af\u30c8\u30c3\u30d7\u30a2\u30d7\u30ea\u3092\u3054\u5229\u7528\u304f\u3060\u3055\u3044\u3002\nerror-javascript-config =\n JavaScript\u306e\u8a2d\u5b9a\u304c\u6b63\u3057\u304f\u306a\u3044\u305f\u3081\u3001Ruffle\u3067\u554f\u984c\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\n \u30b5\u30fc\u30d0\u30fc\u7ba1\u7406\u8005\u306e\u65b9\u306f\u3001\u30a8\u30e9\u30fc\u306e\u8a73\u7d30\u304b\u3089\u3001\u3069\u306e\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc\u306b\u554f\u984c\u304c\u3042\u308b\u306e\u304b\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n Ruffle\u306ewiki\u3092\u53c2\u7167\u3059\u308b\u3053\u3068\u3067\u3001\u89e3\u6c7a\u65b9\u6cd5\u304c\u898b\u3064\u304b\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002\nerror-wasm-not-found =\n Ruffle\u306e\u521d\u671f\u5316\u6642\u306b\u91cd\u5927\u306a\u554f\u984c\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\n \u3053\u306eWeb\u30b5\u30fc\u30d0\u30fc\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u30dd\u30ea\u30b7\u30fc\u304c\u3001\u5b9f\u884c\u306b\u5fc5\u8981\u3068\u306a\u308b\u300c.wasm\u300d\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306e\u5b9f\u884c\u3092\u8a31\u53ef\u3057\u3066\u3044\u307e\u305b\u3093\u3002\u30b5\u30fc\u30d0\u30fc\u306e\u7ba1\u7406\u8005\u306e\u5834\u5408\u306f\u3001\u30d5\u30a1\u30a4\u30eb\u304c\u6b63\u3057\u304f\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3055\u308c\u3066\u3044\u308b\u304b\u78ba\u8a8d\u3092\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u3053\u306e\u554f\u984c\u304c\u89e3\u6c7a\u3057\u306a\u3044\u5834\u5408\u306f\u3001\u300cpublicPath\u300d\u306e\u8a2d\u5b9a\u3092\u4f7f\u7528\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\n \u30b5\u30fc\u30d0\u30fc\u306e\u7ba1\u7406\u8005\u306f\u3001Ruffle\u306ewiki\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002\nerror-wasm-mime-type =\n Ruffle\u306e\u521d\u671f\u5316\u306b\u5931\u6557\u3059\u308b\u5927\u304d\u306a\u554f\u984c\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\n \u3053\u306eWeb\u30b5\u30fc\u30d0\u30fc\u306f\u6b63\u3057\u3044MIME\u30bf\u30a4\u30d7\u306e\u300c.wasm\u300d\u30d5\u30a1\u30a4\u30eb\u3092\u63d0\u4f9b\u3057\u3066\u3044\u307e\u305b\u3093\u3002\n \u30b5\u30fc\u30d0\u30fc\u306e\u7ba1\u7406\u8005\u306f\u3001Ruffle\u306ewiki\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002\nerror-swf-fetch =\n Ruffle\u304cFlash SWF\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\n \u6700\u3082\u8003\u3048\u3089\u308c\u308b\u539f\u56e0\u306f\u3001SWF\u30d5\u30a1\u30a4\u30eb\u304c\u65e2\u306b\u5b58\u5728\u3057\u306a\u3044\u4e8b\u3067Ruffle\u304c\u8aad\u307f\u8fbc\u307f\u306b\u5931\u6557\u3059\u308b\u3068\u3044\u3046\u554f\u984c\u3067\u3059\u3002\n Web\u30b5\u30a4\u30c8\u306e\u7ba1\u7406\u8005\u306b\u304a\u554f\u3044\u5408\u308f\u305b\u304f\u3060\u3055\u3044\u3002\nerror-swf-cors =\n Ruffle\u306fSWF\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\n CORS\u30dd\u30ea\u30b7\u30fc\u306e\u8a2d\u5b9a\u306b\u3088\u308a\u3001fetch\u3078\u306e\u30a2\u30af\u30bb\u30b9\u304c\u30d6\u30ed\u30c3\u30af\u3055\u308c\u3066\u3044\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002\n \u30b5\u30fc\u30d0\u30fc\u7ba1\u7406\u8005\u306e\u65b9\u306f\u3001Ruffle\u306ewiki\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002\nerror-wasm-cors =\n Ruffle\u306b\u5fc5\u8981\u3068\u306a\u308b\u300c.wasm\u300d\u30d5\u30a1\u30a4\u30eb\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306e\u8aad\u307f\u8fbc\u307f\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\n CORS\u30dd\u30ea\u30b7\u30fc\u306b\u3088\u3063\u3066fetch\u3078\u306e\u30a2\u30af\u30bb\u30b9\u304c\u30d6\u30ed\u30c3\u30af\u3055\u308c\u3066\u3044\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002\n \u30b5\u30fc\u30d0\u30fc\u306e\u7ba1\u7406\u8005\u306f\u3001Ruffle wiki\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002\nerror-wasm-invalid =\n Ruffle\u306e\u521d\u671f\u5316\u6642\u306b\u91cd\u5927\u306a\u554f\u984c\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\n \u3053\u306e\u30da\u30fc\u30b8\u306b\u306fRuffle\u3092\u5b9f\u884c\u3059\u308b\u305f\u3081\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3057\u306a\u3044\u304b\u3001\u7121\u52b9\u306a\u30d5\u30a1\u30a4\u30eb\u304c\u3042\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002\n \u30b5\u30fc\u30d0\u30fc\u306e\u7ba1\u7406\u8005\u306f\u3001Ruffle\u306ewiki\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002\nerror-wasm-download =\n Ruffle\u306e\u521d\u671f\u5316\u6642\u306b\u91cd\u5927\u306a\u554f\u984c\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\n \u3053\u306e\u554f\u984c\u306f\u30da\u30fc\u30b8\u3092\u518d\u8aad\u307f\u8fbc\u307f\u3059\u308b\u4e8b\u3067\u5927\u62b5\u306f\u89e3\u6c7a\u3059\u308b\u306f\u305a\u306a\u306e\u3067\u884c\u306a\u3063\u3066\u307f\u3066\u304f\u3060\u3055\u3044\u3002\n \u3082\u3057\u3082\u89e3\u6c7a\u3057\u306a\u3044\u5834\u5408\u306f\u3001Web\u30b5\u30a4\u30c8\u306e\u7ba1\u7406\u8005\u306b\u304a\u554f\u3044\u5408\u308f\u305b\u304f\u3060\u3055\u3044\u3002\nerror-wasm-disabled-on-edge =\n Ruffle\u306b\u5fc5\u8981\u3068\u306a\u308b\u300c.wasm\u300d\u30d5\u30a1\u30a4\u30eb\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306e\u8aad\u307f\u8fbc\u307f\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\n \u3053\u306e\u554f\u984c\u3092\u89e3\u6c7a\u3059\u308b\u306b\u306f\u30d6\u30e9\u30a6\u30b6\u30fc\u306e\u8a2d\u5b9a\u3092\u958b\u304d\u3001\u300c\u30d7\u30e9\u30a4\u30d0\u30b7\u30fc\u3001\u691c\u7d22\u3001\u30b5\u30fc\u30d3\u30b9\u300d\u3092\u30af\u30ea\u30c3\u30af\u3057\u3001\u4e0b\u306b\u30b9\u30af\u30ed\u30fc\u30eb\u3067\u300cWeb\u4e0a\u306e\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u3092\u5f37\u5316\u3059\u308b\u300d\u3092\u30aa\u30d5\u306b\u3057\u3066\u307f\u3066\u304f\u3060\u3055\u3044\u3002\n \u3053\u308c\u3067\u5fc5\u8981\u3068\u306a\u308b\u300c.wasm\u300d\u30d5\u30a1\u30a4\u30eb\u304c\u8aad\u307f\u8fbc\u307e\u308c\u308b\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002\n \u305d\u308c\u3067\u3082\u554f\u984c\u304c\u89e3\u6c7a\u3057\u306a\u3044\u5834\u5408\u3001\u5225\u306e\u30d6\u30e9\u30a6\u30b6\u30fc\u3092\u4f7f\u7528\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002\nerror-javascript-conflict =\n Ruffle\u306e\u521d\u671f\u5316\u6642\u306b\u91cd\u5927\u306a\u554f\u984c\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\n \u3053\u306e\u30da\u30fc\u30b8\u3067\u306fRuffle\u3068\u7af6\u5408\u3059\u308bJavaScript\u30b3\u30fc\u30c9\u304c\u4f7f\u7528\u3055\u308c\u3066\u3044\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002\n \u30b5\u30fc\u30d0\u30fc\u306e\u7ba1\u7406\u8005\u306f\u3001\u7a7a\u767d\u306e\u30da\u30fc\u30b8\u3067\u30d5\u30a1\u30a4\u30eb\u3092\u8aad\u307f\u8fbc\u307f\u3057\u76f4\u3057\u3066\u307f\u3066\u304f\u3060\u3055\u3044\u3002\nerror-javascript-conflict-outdated = \u65b0\u3057\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u306eRuffle\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3059\u308b\u3053\u3068\u3067\u3001\u3053\u306e\u554f\u984c\u3092\u56de\u907f\u3067\u304d\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002(\u73fe\u5728\u306e\u30d3\u30eb\u30c9\u306f\u53e4\u3044\u7269\u3067\u3059:{ $buildDate })\nerror-csp-conflict =\n Ruffle\u306e\u521d\u671f\u5316\u6642\u306b\u91cd\u5927\u306a\u554f\u984c\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\n \u3053\u306eWeb\u30b5\u30fc\u30d0\u30fc\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u30dd\u30ea\u30b7\u30fc\u304c\u5b9f\u884c\u306b\u5fc5\u8981\u3068\u306a\u308b\u300c.wasm\u300d\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306e\u5b9f\u884c\u3092\u8a31\u53ef\u3057\u3066\u3044\u307e\u305b\u3093\u3002\n \u30b5\u30fc\u30d0\u30fc\u306e\u7ba1\u7406\u8005\u306f\u3001Ruffle\u306ewiki\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002\nerror-unknown =\n Flash\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u8868\u793a\u3059\u308b\u969b\u306bRuffle\u3067\u554f\u984c\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\n { $outdated ->\n [true] \u73fe\u5728\u4f7f\u7528\u3057\u3066\u3044\u308b\u30d3\u30eb\u30c9\u306f\u6700\u65b0\u3067\u306f\u306a\u3044\u305f\u3081\u3001\u30b5\u30fc\u30d0\u30fc\u7ba1\u7406\u8005\u306e\u65b9\u306f\u3001\u6700\u65b0\u7248\u306eRuffle\u306b\u66f4\u65b0\u3057\u3066\u307f\u3066\u304f\u3060\u3055\u3044(\u73fe\u5728\u5229\u7528\u4e2d\u306e\u30d3\u30eb\u30c9: { $buildDate })\u3002\n *[false] \u60f3\u5b9a\u5916\u306e\u554f\u984c\u306a\u306e\u3067\u3001\u30d0\u30b0\u3068\u3057\u3066\u5831\u544a\u3057\u3066\u3044\u305f\u3060\u3051\u308b\u3068\u5b09\u3057\u3044\u3067\u3059!\n }\n',"save-manager.ftl":"save-delete-prompt = \u3053\u306e\u30bb\u30fc\u30d6\u30d5\u30a1\u30a4\u30eb\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b?\nsave-reload-prompt =\n \u30bb\u30fc\u30d6\u30d5\u30a1\u30a4\u30eb\u3092\u7af6\u5408\u306e\u53ef\u80fd\u6027\u306a\u304f { $action ->\n [delete] \u524a\u9664\u3059\u308b\n *[replace] \u7f6e\u304d\u63db\u3048\u308b\n } \u305f\u3081\u306b\u3001\u3053\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u518d\u8aad\u307f\u8fbc\u307f\u3059\u308b\u3053\u3068\u3092\u63a8\u5968\u3057\u307e\u3059\u3002\u7d9a\u884c\u3057\u307e\u3059\u304b\uff1f\nsave-download = \u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\nsave-replace = \u7f6e\u304d\u63db\u3048\nsave-delete = \u524a\u9664\nsave-backup-all = \u3059\u3079\u3066\u306e\u30bb\u30fc\u30d6\u30d5\u30a1\u30a4\u30eb\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\n","volume-controls.ftl":"volume-controls = \u97f3\u91cf\nvolume-controls-mute = \u6d88\u97f3\nvolume-controls-volume = \u97f3\u91cf\n"},"ko-KR":{"context_menu.ftl":"context-menu-download-swf = .swf \ub2e4\uc6b4\ub85c\ub4dc\ncontext-menu-copy-debug-info = \ub514\ubc84\uadf8 \uc815\ubcf4 \ubcf5\uc0ac\ncontext-menu-open-save-manager = \uc800\uc7a5 \uad00\ub9ac\uc790 \uc5f4\uae30\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] Ruffle \ud655\uc7a5 \ud504\ub85c\uadf8\ub7a8 \uc815\ubcf4 ({ $version })\n *[other] Ruffle \uc815\ubcf4 ({ $version })\n }\ncontext-menu-hide = \uc774 \uba54\ub274 \uc228\uae30\uae30\ncontext-menu-exit-fullscreen = \uc804\uccb4\ud654\uba74 \ub098\uac00\uae30\ncontext-menu-enter-fullscreen = \uc804\uccb4\ud654\uba74\uc73c\ub85c \uc5f4\uae30\ncontext-menu-volume-controls = \uc74c\ub7c9 \uc870\uc808\n","messages.ftl":'message-cant-embed = Ruffle\uc774 \uc774 \ud398\uc774\uc9c0\uc5d0 \ud3ec\ud568\ub41c \ud50c\ub798\uc2dc\ub97c \uc2e4\ud589\ud560 \uc218 \uc5c6\uc5c8\uc2b5\ub2c8\ub2e4. \ubcc4\ub3c4\uc758 \ud0ed\uc5d0\uc11c \ud30c\uc77c\uc744 \uc5f4\uc5b4\ubd04\uc73c\ub85c\uc11c \uc774 \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\npanic-title = \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4 :(\nmore-info = \ucd94\uac00 \uc815\ubcf4\nrun-anyway = \uadf8\ub798\ub3c4 \uc2e4\ud589\ud558\uae30\ncontinue = \uacc4\uc18d\ud558\uae30\nreport-bug = \ubc84\uadf8 \uc81c\ubcf4\nupdate-ruffle = Ruffle \uc5c5\ub370\uc774\ud2b8\nruffle-demo = \uc6f9 \ub370\ubaa8\nruffle-desktop = \ub370\uc2a4\ud06c\ud1b1 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\nruffle-wiki = Ruffle \uc704\ud0a4 \ubcf4\uae30\nenable-hardware-acceleration = \ud558\ub4dc\uc6e8\uc5b4 \uac00\uc18d\uc774 \ud65c\uc131\ud654\ub418\uc9c0 \uc54a\uc740 \uac83 \uac19\uc2b5\ub2c8\ub2e4. Ruffle\uc740 \uacc4\uc18d \uc791\ub3d9\ud558\uc9c0\ub9cc \uc2e4\ud589 \uc18d\ub3c4\uac00 \ub9e4\uc6b0 \ub290\ub9b4 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \ud558\ub4dc\uc6e8\uc5b4 \uac00\uc18d\uc744 \ud65c\uc131\ud654\ud558\ub294 \ubc29\ubc95\uc744 \uc54c\uc544\ubcf4\ub824\uba74 \ub2e4\uc74c \ub9c1\ud06c\ub97c \ucc38\uace0\ud574\ubcf4\uc138\uc694.\nview-error-details = \uc624\ub958 \uc138\ubd80 \uc815\ubcf4 \ubcf4\uae30\nopen-in-new-tab = \uc0c8 \ud0ed\uc5d0\uc11c \uc5f4\uae30\nclick-to-unmute = \ud074\ub9ad\ud558\uc5ec \uc74c\uc18c\uac70 \ud574\uc81c\nerror-file-protocol =\n Ruffle\uc744 "file:" \ud504\ub85c\ud1a0\ucf5c\uc5d0\uc11c \uc2e4\ud589\ud558\uace0 \uc788\ub294 \uac83\uc73c\ub85c \ubcf4\uc785\ub2c8\ub2e4.\n \ube0c\ub77c\uc6b0\uc800\uc5d0\uc11c\ub294 \uc774 \ud504\ub85c\ud1a0\ucf5c\uc744 \ubcf4\uc548\uc0c1\uc758 \uc774\uc720\ub85c \ub9ce\uc740 \uae30\ub2a5\uc744 \uc791\ub3d9\ud558\uc9c0 \uc54a\uac8c \ucc28\ub2e8\ud558\ubbc0\ub85c \uc774 \ubc29\ubc95\uc740 \uc791\ub3d9\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.\n \ub300\uc2e0, \ub85c\uceec \uc11c\ubc84\ub97c \uc9c1\uc811 \uc5f4\uc5b4\uc11c \uc124\uc815\ud558\uac70\ub098 \uc6f9 \ub370\ubaa8 \ub610\ub294 \ub370\uc2a4\ud06c\ud1b1 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uc0ac\uc6a9\ud558\uc2dc\uae30 \ubc14\ub78d\ub2c8\ub2e4.\nerror-javascript-config =\n \uc798\ubabb\ub41c \uc790\ubc14\uc2a4\ud06c\ub9bd\ud2b8 \uc124\uc815\uc73c\ub85c \uc778\ud574 Ruffle\uc5d0\uc11c \uc911\ub300\ud55c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.\n \ub9cc\uc57d \ub2f9\uc2e0\uc774 \uc11c\ubc84 \uad00\ub9ac\uc790\uc778 \uacbd\uc6b0, \uc624\ub958 \uc138\ubd80\uc0ac\ud56d\uc744 \ud655\uc778\ud558\uc5ec \uc5b4\ub5a4 \ub9e4\uac1c\ubcc0\uc218\uac00 \uc798\ubabb\ub418\uc5c8\ub294\uc9c0 \uc54c\uc544\ubcf4\uc138\uc694.\n \ub610\ub294 Ruffle \uc704\ud0a4\ub97c \ud1b5\ud574 \ub3c4\uc6c0\uc744 \ubc1b\uc544 \ubcfc \uc218\ub3c4 \uc788\uc2b5\ub2c8\ub2e4.\nerror-wasm-not-found =\n Ruffle\uc774 ".wasm" \ud544\uc218 \ud30c\uc77c \uad6c\uc131\uc694\uc18c\ub97c \ub85c\ub4dc\ud558\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4.\n \ub9cc\uc57d \ub2f9\uc2e0\uc774 \uc11c\ubc84 \uad00\ub9ac\uc790\ub77c\uba74 \ud30c\uc77c\uc774 \uc62c\ubc14\ub974\uac8c \uc5c5\ub85c\ub4dc\ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud558\uc138\uc694.\n \ubb38\uc81c\uac00 \uc9c0\uc18d\ub41c\ub2e4\uba74 "publicPath" \uc635\uc158\uc744 \uc0ac\uc6a9\ud574\uc57c \ud560 \uc218\ub3c4 \uc788\uc2b5\ub2c8\ub2e4: Ruffle \uc704\ud0a4\ub97c \ucc38\uc870\ud558\uc5ec \ub3c4\uc6c0\uc744 \ubc1b\uc73c\uc138\uc694.\nerror-wasm-mime-type =\n Ruffle\uc774 \ucd08\uae30\ud654\ub97c \uc2dc\ub3c4\ud558\ub294 \ub3d9\uc548 \uc911\ub300\ud55c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.\n \uc774 \uc6f9 \uc11c\ubc84\ub294 \uc62c\ubc14\ub978 MIME \uc720\ud615\uc758 ".wasm" \ud30c\uc77c\uc744 \uc81c\uacf5\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.\n \ub9cc\uc57d \ub2f9\uc2e0\uc774 \uc11c\ubc84 \uad00\ub9ac\uc790\ub77c\uba74 Ruffle \uc704\ud0a4\ub97c \ud1b5\ud574 \ub3c4\uc6c0\uc744 \ubc1b\uc73c\uc138\uc694.\nerror-swf-fetch =\n Ruffle\uc774 \ud50c\ub798\uc2dc SWF \ud30c\uc77c\uc744 \ub85c\ub4dc\ud558\ub294 \ub370 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.\n \uc774\ub294 \uc8fc\ub85c \ud30c\uc77c\uc774 \ub354 \uc774\uc0c1 \uc874\uc7ac\ud558\uc9c0 \uc54a\uc544 Ruffle\uc774 \ub85c\ub4dc\ud560 \uc218 \uc788\ub294 \uac83\uc774 \uc5c6\uc744 \uac00\ub2a5\uc131\uc774 \ub192\uc2b5\ub2c8\ub2e4.\n \uc6f9\uc0ac\uc774\ud2b8 \uad00\ub9ac\uc790\uc5d0\uac8c \ubb38\uc758\ud558\uc5ec \ub3c4\uc6c0\uc744 \ubc1b\uc544\ubcf4\uc138\uc694.\nerror-swf-cors =\n Ruffle\uc774 \ud50c\ub798\uc2dc SWF \ud30c\uc77c\uc744 \ub85c\ub4dc\ud558\ub294 \ub370 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.\n CORS \uc815\ucc45\uc5d0 \uc758\ud574 \ub370\uc774\ud130 \uac00\uc838\uc624\uae30\uc5d0 \ub300\ud55c \uc561\uc138\uc2a4\uac00 \ucc28\ub2e8\ub418\uc5c8\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\n \ub9cc\uc57d \ub2f9\uc2e0\uc774 \uc11c\ubc84 \uad00\ub9ac\uc790\ub77c\uba74 Ruffle \uc704\ud0a4\ub97c \ucc38\uc870\ud558\uc5ec \ub3c4\uc6c0\uc744 \ubc1b\uc544\ubcfc \uc218 \uc788\uc2b5\ub2c8\ub2e4.\nerror-wasm-cors =\n Ruffle\uc774 ".wasm" \ud544\uc218 \ud30c\uc77c \uad6c\uc131\uc694\uc18c\ub97c \ub85c\ub4dc\ud558\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4.\n CORS \uc815\ucc45\uc5d0 \uc758\ud574 \ub370\uc774\ud130 \uac00\uc838\uc624\uae30\uc5d0 \ub300\ud55c \uc561\uc138\uc2a4\uac00 \ucc28\ub2e8\ub418\uc5c8\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\n \ub9cc\uc57d \ub2f9\uc2e0\uc774 \uc11c\ubc84 \uad00\ub9ac\uc790\ub77c\uba74 Ruffle \uc704\ud0a4\ub97c \ucc38\uc870\ud558\uc5ec \ub3c4\uc6c0\uc744 \ubc1b\uc544\ubcfc \uc218 \uc788\uc2b5\ub2c8\ub2e4.\nerror-wasm-invalid =\n Ruffle\uc774 \ucd08\uae30\ud654\ub97c \uc2dc\ub3c4\ud558\ub294 \ub3d9\uc548 \uc911\ub300\ud55c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.\n \uc774 \ud398\uc774\uc9c0\uc5d0 Ruffle\uc744 \uc2e4\ud589\ud558\uae30 \uc704\ud55c \ud30c\uc77c\uc774 \ub204\ub77d\ub418\uc5c8\uac70\ub098 \uc798\ubabb\ub41c \uac83 \uac19\uc2b5\ub2c8\ub2e4.\n \ub9cc\uc57d \ub2f9\uc2e0\uc774 \uc11c\ubc84 \uad00\ub9ac\uc790\ub77c\uba74 Ruffle \uc704\ud0a4\ub97c \ucc38\uc870\ud558\uc5ec \ub3c4\uc6c0\uc744 \ubc1b\uc544\ubcfc \uc218 \uc788\uc2b5\ub2c8\ub2e4.\nerror-wasm-download =\n Ruffle\uc774 \ucd08\uae30\ud654\ub97c \uc2dc\ub3c4\ud558\ub294 \ub3d9\uc548 \uc911\ub300\ud55c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.\n \uc774 \ubb38\uc81c\ub294 \ub54c\ub54c\ub85c \ubc14\ub85c \ud574\uacb0\ub420 \uc218 \uc788\uc73c\ubbc0\ub85c \ud398\uc774\uc9c0\ub97c \uc0c8\ub85c\uace0\uce68\ud558\uc5ec \ub2e4\uc2dc \uc2dc\ub3c4\ud574\ubcf4\uc138\uc694.\n \uadf8\ub798\ub3c4 \ubb38\uc81c\uac00 \uc9c0\uc18d\ub41c\ub2e4\uba74, \uc6f9\uc0ac\uc774\ud2b8 \uad00\ub9ac\uc790\uc5d0\uac8c \ubb38\uc758\ud574\uc8fc\uc138\uc694.\nerror-wasm-disabled-on-edge =\n Ruffle\uc774 ".wasm" \ud544\uc218 \ud30c\uc77c \uad6c\uc131\uc694\uc18c\ub97c \ub85c\ub4dc\ud558\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4.\n \uc774\ub97c \ud574\uacb0\ud558\ub824\uba74 \ube0c\ub77c\uc6b0\uc800 \uc124\uc815\uc5d0\uc11c "\uac1c\uc778 \uc815\ubcf4, \uac80\uc0c9 \ubc0f \uc11c\ube44\uc2a4"\ub97c \ud074\ub9ad\ud55c \ud6c4, \ud558\ub2e8\uc73c\ub85c \uc2a4\ud06c\ub864\ud558\uc5ec "\uc6f9\uc5d0\uc11c \ubcf4\uc548 \uac15\ud654" \uae30\ub2a5\uc744 \uaebc\uc57c \ud569\ub2c8\ub2e4.\n \uc774\ub294 \ud544\uc694\ud55c ".wasm" \ud30c\uc77c\uc744 \ube0c\ub77c\uc6b0\uc800\uc5d0\uc11c \ub85c\ub4dc\ud560 \uc218 \uc788\ub3c4\ub85d \ud5c8\uc6a9\ud569\ub2c8\ub2e4.\n \uc774 \ubb38\uc81c\uac00 \uc9c0\uc18d\ub420 \uacbd\uc6b0 \ub2e4\ub978 \ube0c\ub77c\uc6b0\uc800\ub97c \uc0ac\uc6a9\ud574\uc57c \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\nerror-javascript-conflict =\n Ruffle\uc774 \ucd08\uae30\ud654\ub97c \uc2dc\ub3c4\ud558\ub294 \ub3d9\uc548 \uc911\ub300\ud55c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.\n \uc774 \ud398\uc774\uc9c0\uc5d0\uc11c \uc0ac\uc6a9\ub418\ub294 \uc790\ubc14\uc2a4\ud06c\ub9bd\ud2b8 \ucf54\ub4dc\uac00 Ruffle\uacfc \ucda9\ub3cc\ud558\ub294 \uac83\uc73c\ub85c \ubcf4\uc785\ub2c8\ub2e4.\n \ub9cc\uc57d \ub2f9\uc2e0\uc774 \uc11c\ubc84 \uad00\ub9ac\uc790\ub77c\uba74 \ube48 \ud398\uc774\uc9c0\uc5d0\uc11c \ud30c\uc77c\uc744 \ub85c\ub4dc\ud574\ubcf4\uc138\uc694.\nerror-javascript-conflict-outdated = \ub610\ud55c Ruffle\uc758 \ucd5c\uc2e0 \ubc84\uc804\uc744 \uc5c5\ub85c\ub4dc\ud558\ub294 \uac83\uc744 \uc2dc\ub3c4\ud558\uc5ec \ubb38\uc81c\ub97c \uc6b0\ud68c\ud574\ubcfc \uc218 \uc788\uc2b5\ub2c8\ub2e4. (\ud604\uc7ac \ube4c\ub4dc\uac00 \uc624\ub798\ub418\uc5c8\uc2b5\ub2c8\ub2e4: { $buildDate }).\nerror-csp-conflict =\n Ruffle\uc774 \ucd08\uae30\ud654\ub97c \uc2dc\ub3c4\ud558\ub294 \ub3d9\uc548 \uc911\ub300\ud55c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.\n \uc774 \uc6f9 \uc11c\ubc84\uc758 CSP(Content Security Policy) \uc815\ucc45\uc774 ".wasm" \ud544\uc218 \uad6c\uc131\uc694\uc18c\ub97c \uc2e4\ud589\ud558\ub294 \uac83\uc744 \ud5c8\uc6a9\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.\n \ub9cc\uc57d \ub2f9\uc2e0\uc774 \uc11c\ubc84 \uad00\ub9ac\uc790\ub77c\uba74 Ruffle \uc704\ud0a4\ub97c \ucc38\uc870\ud558\uc5ec \ub3c4\uc6c0\uc744 \ubc1b\uc544\ubcfc \uc218 \uc788\uc2b5\ub2c8\ub2e4.\nerror-unknown =\n Ruffle\uc774 \ud50c\ub798\uc2dc \ucf58\ud150\uce20\ub97c \ud45c\uc2dc\ud558\ub824\uace0 \uc2dc\ub3c4\ud558\ub294 \ub3d9\uc548 \uc911\ub300\ud55c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.\n { $outdated ->\n [true] \ub9cc\uc57d \ub2f9\uc2e0\uc774 \uc11c\ubc84 \uad00\ub9ac\uc790\ub77c\uba74, Ruffle\uc758 \ucd5c\uc2e0 \ubc84\uc804\uc744 \uc5c5\ub85c\ub4dc\ud558\uc5ec \ub2e4\uc2dc \uc2dc\ub3c4\ud574\ubcf4\uc138\uc694. (\ud604\uc7ac \ube4c\ub4dc\uac00 \uc624\ub798\ub418\uc5c8\uc2b5\ub2c8\ub2e4: { $buildDate }).\n *[false] \uc774\ub7f0 \ud604\uc0c1\uc774 \ubc1c\uc0dd\ud574\uc11c\ub294 \uc548\ub418\ubbc0\ub85c, \ubc84\uadf8\ub97c \uc81c\ubcf4\ud574\uc8fc\uc2e0\ub2e4\uba74 \uac10\uc0ac\ud558\uaca0\uc2b5\ub2c8\ub2e4!\n }\n',"save-manager.ftl":"save-delete-prompt = \uc815\ub9d0\ub85c \uc774 \uc138\uc774\ube0c \ud30c\uc77c\uc744 \uc0ad\uc81c\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?\nsave-reload-prompt =\n \b\uc774 \ud30c\uc77c\uc744 \uc7a0\uc7ac\uc801\uc778 \ucda9\ub3cc \uc5c6\uc774 { $action ->\n [delete] \uc0ad\uc81c\n *[replace] \uad50\uccb4\n }\ud558\ub824\uba74 \ucf58\ud150\uce20\ub97c \ub2e4\uc2dc \ub85c\ub4dc\ud574\uc57c \ud569\ub2c8\ub2e4. \uadf8\ub798\ub3c4 \uacc4\uc18d\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?\nsave-download = \ub2e4\uc6b4\ub85c\ub4dc\nsave-replace = \uad50\uccb4\nsave-delete = \uc0ad\uc81c\nsave-backup-all = \ubaa8\ub4e0 \uc800\uc7a5 \ud30c\uc77c \ub2e4\uc6b4\ub85c\ub4dc\n","volume-controls.ftl":"volume-controls = \uc74c\ub7c9 \uc870\uc808\nvolume-controls-mute = \uc74c\uc18c\uac70\nvolume-controls-volume = \uc74c\ub7c9\n"},"nl-NL":{"context_menu.ftl":"context-menu-download-swf = .swf downloaden\ncontext-menu-copy-debug-info = Kopieer debuginformatie\ncontext-menu-open-save-manager = Open opgeslagen-data-manager\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] Over Ruffle Uitbreiding ({ $version })\n *[other] Over Ruffle ({ $version })\n }\ncontext-menu-hide = Verberg dit menu\ncontext-menu-exit-fullscreen = Verlaat volledig scherm\ncontext-menu-enter-fullscreen = Naar volledig scherm\ncontext-menu-volume-controls = Geluidsniveaus\n","messages.ftl":'message-cant-embed =\n Ruffle kon de Flash-inhoud op de pagina niet draaien.\n Je kan proberen het bestand in een apart tabblad te openen, om hier omheen te werken.\npanic-title = Er ging iets mis :(\nmore-info = Meer informatie\nrun-anyway = Toch starten\ncontinue = Doorgaan\nreport-bug = Bug rapporteren\nupdate-ruffle = Ruffle updaten\nruffle-demo = Web Demo\nruffle-desktop = Desktopapplicatie\nruffle-wiki = Bekijk de Ruffle Wiki\nenable-hardware-acceleration = Het lijkt erop dat hardwareversnelling niet beschikbaar is. Ruffle zal werken, maar gaat waarschijnlijk erg traag zijn. Je kan lezen hoe hardwareversnelling in te schakelen is door deze link te volgen.\nview-error-details = Foutdetails tonen\nopen-in-new-tab = Openen in een nieuw tabblad\nclick-to-unmute = Klik om te ontdempen\nerror-file-protocol =\n Het lijkt erop dat je Ruffle gebruikt met het "file" protocol.\n De meeste browsers blokkeren dit om veiligheidsredenen, waardoor het niet werkt.\n In plaats hiervan raden we aan om een lokale server te draaien, de web demo te gebruiken, of de desktopapplicatie.\nerror-javascript-config =\n Ruffle heeft een groot probleem ondervonden vanwege een onjuiste JavaScript configuratie.\n Als je de serverbeheerder bent, kijk dan naar de foutdetails om te zien wat er verkeerd is.\n Je kan ook in de Ruffle wiki kijken voor hulp.\nerror-wasm-not-found =\n Ruffle kon het vereiste ".wasm" bestandscomponent niet laden.\n Als je de serverbeheerder bent, controleer dan of het bestaand juist is ge\xfcpload.\n Mocht het probleem blijven voordoen, moet je misschien de "publicPath" instelling gebruiken: zie ook de Ruffle wiki voor hulp.\nerror-wasm-mime-type =\n Ruffle heeft een groot probleem ondervonden tijdens het initialiseren.\n Deze webserver serveert ".wasm" bestanden niet met het juiste MIME type.\n Als je de serverbeheerder bent, kijk dan in de Ruffle wiki voor hulp.\nerror-swf-fetch =\n Ruffle kon het Flash SWF bestand niet inladen.\n De meest waarschijnlijke reden is dat het bestand niet langer bestaat, en er dus niets is om in te laden.\n Probeer contact op te nemen met de websitebeheerder voor hulp.\nerror-swf-cors =\n Ruffle kon het Flash SWD bestand niet inladen.\n Toegang is waarschijnlijk geblokeerd door het CORS beleid.\n Als je de serverbeheerder bent, kijk dan in de Ruffle wiki voor hulp.\nerror-wasm-cors =\n Ruffle kon het vereiste ".wasm" bestandscomponent niet laden.\n Toegang is waarschijnlijk geblokeerd door het CORS beleid.\n Als je de serverbeheerder bent, kijk dan in de Ruffle wiki voor hulp.\nerror-wasm-invalid =\n Ruffle heeft een groot probleem ondervonden tijdens het initialiseren.\n Het lijkt erop dat de Ruffle bestanden ontbreken of ongeldig zijn.\n Als je de serverbeheerder bent, kijk dan in de Ruffle wiki voor hulp.\nerror-wasm-download =\n Ruffle heeft een groot probleem ondervonden tijdens het initialiseren.\n Dit lost zichzelf vaak op als je de bladzijde opnieuw inlaadt.\n Zo niet, neem dan contact op met de websitebeheerder.\nerror-wasm-disabled-on-edge =\n Ruffle kon het vereiste ".wasm" bestandscomponent niet laden.\n Om dit op te lossen, ga naar je browserinstellingen, klik op "Privacy, zoeken en diensten", scroll omlaag, en schakel "Verbeter je veiligheid op he web" uit.\n Dan kan je browser wel de vereiste ".wasm" bestanden inladen.\n Als het probleem zich blijft voordoen, moet je misschien een andere browser gebruiken.\nerror-javascript-conflict =\n Ruffle heeft een groot probleem ondervonden tijdens het initialiseren.\n Het lijkt erop dat deze pagina JavaScript code gebruikt die conflicteert met Ruffle.\n Als je de serverbeheerder bent, raden we aan om het bestand op een lege pagina te proberen in te laden.\nerror-javascript-conflict-outdated = Je kan ook proberen een nieuwe versie van Ruffle te installeren, om om het probleem heen te werken (huidige versie is oud: { $buildDate }).\nerror-csp-conflict =\n Ruffle heeft een groot probleem ondervonden tijdens het initialiseren.\n Het CSP-beleid staat niet toe dat het vereiste ".wasm" component kan draaien.\n Als je de serverbeheerder bent, kijk dan in de Ruffle wiki voor hulp.\nerror-unknown =\n Ruffle heeft een groot probleem onderbonden tijdens het weergeven van deze Flash-inhoud.\n { $outdated ->\n [true] Als je de serverbeheerder bent, upload dan een nieuwe versie van Ruffle (huidige versie is oud: { $buildDate }).\n *[false] Dit hoort niet te gebeuren, dus we stellen het op prijs als je de fout aan ons rapporteert!\n }\n',"save-manager.ftl":"save-delete-prompt = Weet je zeker dat je deze opgeslagen data wilt verwijderen?\nsave-reload-prompt =\n De enige manier om deze opgeslagen data te { $action ->\n [delete] verwijderen\n *[replace] vervangen\n } zonder potenti\xeble problemen is door de inhoud opnieuw te laden. Toch doorgaan?\nsave-download = Downloaden\nsave-replace = Vervangen\nsave-delete = Verwijderen\nsave-backup-all = Download alle opgeslagen data\n","volume-controls.ftl":"volume-controls = Geluidsniveaus\nvolume-controls-mute = Dempen\nvolume-controls-volume = Volume\n"},"pl-PL":{"context_menu.ftl":"context-menu-download-swf = Pobierz .swf\ncontext-menu-copy-debug-info = Kopiuj informacje debugowania\ncontext-menu-open-save-manager = Otw\xf3rz Menad\u017cer Zapis\xf3w\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] O Rozszerzeniu Ruffle ({ $version })\n *[other] O Ruffle ({ $version })\n }\ncontext-menu-hide = Ukryj to menu\ncontext-menu-exit-fullscreen = Zamknij pe\u0142ny ekran\ncontext-menu-enter-fullscreen = Pe\u0142ny ekran\ncontext-menu-volume-controls = Sterowanie g\u0142o\u015bno\u015bci\u0105\n","messages.ftl":'message-cant-embed =\n Ruffle nie by\u0142o w stanie uruchomi\u0107 zawarto\u015bci Flash w tej stronie.\n Mo\u017cesz spr\xf3bowa\u0107 otworzy\u0107 plik w nowej karcie, aby unikn\u0105\u0107 tego problemu.\npanic-title = Co\u015b posz\u0142o nie tak :(\nmore-info = Wi\u0119cej informacji\nrun-anyway = Uruchom mimo tego\ncontinue = Kontynuuj\nreport-bug = Zg\u0142o\u015b b\u0142\u0105d\nupdate-ruffle = Zaktualizuj Ruffle\nruffle-desktop = Aplikacja na komputer\nruffle-wiki = Zobacz Wiki Ruffle\nenable-hardware-acceleration = Wygl\u0105da na to, \u017ce akceleracja sprz\u0119towa nie jest w\u0142\u0105czona. Chocia\u017c Ruffle mo\u017ce dzia\u0142a\u0107, mo\u017ce by\u0107 nieproporcjonalnie wolna. Mo\u017cesz dowiedzie\u0107 si\u0119, jak w\u0142\u0105czy\u0107 akceleracj\u0119 sprz\u0119tow\u0105, pod\u0105\u017caj\u0105c za tym linkiem.\nview-error-details = Zobacz szczeg\xf3\u0142y b\u0142\u0119du\nopen-in-new-tab = Otw\xf3rz w nowej karcie\nclick-to-unmute = Kliknij aby wy\u0142\u0105czy\u0107 wyciszenie\nerror-file-protocol =\n Wygl\u0105da na to, \u017ce u\u017cywasz Ruffle w protokole "plik:".\n To nie dzia\u0142a poniewa\u017c przegl\u0105darka blokuje wiele funkcji przed dzia\u0142aniem ze wzgl\u0119d\xf3w bezpiecze\u0144stwa.\n Zamiast tego zapraszamy do konfiguracji serwera lokalnego lub u\u017cycia aplikacji demo lub desktopowej.\nerror-javascript-config =\n Ruffle napotka\u0142 powa\u017cny problem z powodu nieprawid\u0142owej konfiguracji JavaScript.\n Je\u015bli jeste\u015b administratorem serwera, prosimy o sprawdzenie szczeg\xf3\u0142\xf3w b\u0142\u0119du, aby dowiedzie\u0107 si\u0119, kt\xf3ry parametr jest b\u0142\u0119dny.\n Mo\u017cesz r\xf3wnie\u017c zapozna\u0107 si\u0119 z wiki Ruffle po pomoc.\nerror-wasm-not-found =\n Ruffle nie uda\u0142o si\u0119 za\u0142adowa\u0107 wymaganego komponentu pliku ".wasm".\n Je\u015bli jeste\u015b administratorem serwera, upewnij si\u0119, \u017ce plik zosta\u0142 poprawnie przes\u0142any.\n Je\u015bli problem b\u0119dzie si\u0119 powtarza\u0142, by\u0107 mo\u017ce b\u0119dziesz musia\u0142 u\u017cy\u0107 ustawienia "publicPath": zapoznaj si\u0119 z wiki Ruffle aby uzyska\u0107 pomoc.\nerror-wasm-mime-type =\n Ruffle napotka\u0142 powa\u017cny problem podczas pr\xf3by zainicjowania.\n Ten serwer internetowy nie obs\u0142uguje ". asm" pliki z poprawnym typem MIME.\n Je\u015bli jeste\u015b administratorem serwera, zapoznaj si\u0119 z wiki Ruffle aby uzyska\u0107 pomoc.\nerror-swf-fetch =\n Ruffle nie uda\u0142o si\u0119 za\u0142adowa\u0107 pliku Flash SWF.\n Najbardziej prawdopodobnym powodem jest to, \u017ce plik ju\u017c nie istnieje, wi\u0119c Ruffle nie ma nic do za\u0142adowania.\n Spr\xf3buj skontaktowa\u0107 si\u0119 z administratorem witryny, aby uzyska\u0107 pomoc.\nerror-swf-cors =\n Ruffle nie uda\u0142o si\u0119 za\u0142adowa\u0107 pliku Flash SWF.\n Dost\u0119p do pobierania zosta\u0142 prawdopodobnie zablokowany przez polityk\u0119 CORS.\n Je\u015bli jeste\u015b administratorem serwera, prosimy o pomoc z wiki Ruffle.\nerror-wasm-cors =\n Ruffle nie uda\u0142o si\u0119 za\u0142adowa\u0107 wymaganego komponentu pliku ".wasm".\n Dost\u0119p do pobierania zosta\u0142 prawdopodobnie zablokowany przez polityk\u0119 CORS.\n Je\u015bli jeste\u015b administratorem serwera, prosimy o pomoc z wiki Ruffle.\nerror-wasm-invalid =\n Ruffle napotka\u0142 powa\u017cny problem podczas pr\xf3by zainicjowania.\n Wygl\u0105da na to, \u017ce ta strona ma brakuj\u0105ce lub nieprawid\u0142owe pliki do uruchomienia Ruffle.\n Je\u015bli jeste\u015b administratorem serwera, prosimy o pomoc z wiki Ruffle.\nerror-wasm-download =\n Ruffle napotka\u0142 powa\u017cny problem podczas pr\xf3by zainicjowania.\n Mo\u017ce to cz\u0119sto rozwi\u0105za\u0107 siebie, wi\u0119c mo\u017cesz spr\xf3bowa\u0107 od\u015bwie\u017cy\u0107 stron\u0119.\n W przeciwnym razie skontaktuj si\u0119 z administratorem witryny.\nerror-wasm-disabled-on-edge =\n Ruffle nie uda\u0142o si\u0119 za\u0142adowa\u0107 wymaganego komponentu pliku ".wasm".\n Aby to naprawi\u0107, spr\xf3buj otworzy\u0107 ustawienia przegl\u0105darki, klikaj\u0105c "Prywatno\u015b\u0107, wyszukiwanie i us\u0142ugi", przewijaj\u0105c w d\xf3\u0142 i wy\u0142\u0105czaj\u0105c "Zwi\u0119ksz bezpiecze\u0144stwo w sieci".\n Pozwoli to przegl\u0105darce za\u0142adowa\u0107 wymagane pliki ".wasm".\n Je\u015bli problem b\u0119dzie si\u0119 powtarza\u0142, by\u0107 mo\u017ce b\u0119dziesz musia\u0142 u\u017cy\u0107 innej przegl\u0105darki.\nerror-javascript-conflict =\n Ruffle napotka\u0142 powa\u017cny problem podczas pr\xf3by zainicjowania.\n Wygl\u0105da na to, \u017ce ta strona u\u017cywa kodu JavaScript, kt\xf3ry koliduje z Ruffle.\n Je\u015bli jeste\u015b administratorem serwera, zapraszamy Ci\u0119 do \u0142adowania pliku na pustej stronie.\nerror-javascript-conflict-outdated = Mo\u017cesz r\xf3wnie\u017c spr\xf3bowa\u0107 przes\u0142a\u0107 nowsz\u0105 wersj\u0119 Ruffle, kt\xf3ra mo\u017ce omin\u0105\u0107 problem (obecna wersja jest przestarza\u0142a: { $buildDate }).\nerror-csp-conflict =\n Ruffle napotka\u0142 powa\u017cny problem podczas pr\xf3by zainicjowania.\n Polityka bezpiecze\u0144stwa zawarto\u015bci tego serwera nie zezwala na wymagany ". wasm" komponent do uruchomienia.\n Je\u015bli jeste\u015b administratorem serwera, zapoznaj si\u0119 z wiki Ruffle po pomoc.\nerror-unknown =\n Ruffle napotka\u0142 powa\u017cny problem podczas pr\xf3by wy\u015bwietlenia tej zawarto\u015bci Flash.\n { $outdated ->\n [true] Je\u015bli jeste\u015b administratorem serwera, spr\xf3buj przes\u0142a\u0107 nowsz\u0105 wersj\u0119 Ruffle (obecna wersja jest przestarza\u0142a: { $buildDate }).\n *[false] To nie powinno si\u0119 wydarzy\u0107, wi\u0119c byliby\u015bmy wdzi\u0119czni, gdyby\u015b m\xf3g\u0142 zg\u0142osi\u0107 b\u0142\u0105d!\n }\n',"save-manager.ftl":"save-delete-prompt = Czy na pewno chcesz skasowa\u0107 ten plik zapisu?\nsave-reload-prompt =\n Jedyn\u0105 opcj\u0105, aby { $action ->\n [delete] usun\u0105\u0107\n *[replace] zamieni\u0107\n } ten plik zapisu bez potencjalnych konflikt\xf3w jest prze\u0142adowanie zawarto\u015bci. Czy chcesz kontynuowa\u0107?\nsave-download = Pobierz\nsave-replace = Zamie\u0144\nsave-delete = Usu\u0144\nsave-backup-all = Pobierz wszystkie pliki zapisu\n","volume-controls.ftl":"volume-controls = Sterowanie g\u0142o\u015bno\u015bci\u0105\nvolume-controls-mute = Wycisz\nvolume-controls-volume = G\u0142o\u015bno\u015b\u0107\n"},"pt-BR":{"context_menu.ftl":"context-menu-download-swf = Baixar .swf\ncontext-menu-copy-debug-info = Copiar informa\xe7\xe3o de depura\xe7\xe3o\ncontext-menu-open-save-manager = Abrir o Gerenciador de Salvamento\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] Sobre a extens\xe3o do Ruffle ({ $version })\n *[other] Sobre o Ruffle ({ $version })\n }\ncontext-menu-hide = Esconder este menu\ncontext-menu-exit-fullscreen = Sair da tela cheia\ncontext-menu-enter-fullscreen = Entrar em tela cheia\n","messages.ftl":'message-cant-embed =\n Ruffle n\xe3o conseguiu executar o Flash incorporado nesta p\xe1gina.\n Voc\xea pode tentar abrir o arquivo em uma guia separada para evitar esse problema.\npanic-title = Algo deu errado :(\nmore-info = Mais informa\xe7\xe3o\nrun-anyway = Executar mesmo assim\ncontinue = Continuar\nreport-bug = Reportar Bug\nupdate-ruffle = Atualizar Ruffle\nruffle-demo = Demo Web\nruffle-desktop = Aplicativo de Desktop\nruffle-wiki = Ver Wiki do Ruffle\nview-error-details = Ver detalhes do erro\nopen-in-new-tab = Abrir em uma nova guia\nclick-to-unmute = Clique para ativar o som\nerror-file-protocol =\n Parece que voc\xea est\xe1 executando o Ruffle no protocolo "file:".\n Isto n\xe3o funciona como navegadores bloqueiam muitos recursos de funcionar por raz\xf5es de seguran\xe7a.\n Ao inv\xe9s disso, convidamos voc\xea a configurar um servidor local ou a usar a demonstra\xe7\xe3o da web, ou o aplicativo de desktop.\nerror-javascript-config =\n O Ruffle encontrou um grande problema devido a uma configura\xe7\xe3o incorreta do JavaScript.\n Se voc\xea for o administrador do servidor, convidamos voc\xea a verificar os detalhes do erro para descobrir qual par\xe2metro est\xe1 com falha.\n Voc\xea tamb\xe9m pode consultar o wiki do Ruffle para obter ajuda.\nerror-wasm-not-found =\n Ruffle falhou ao carregar o componente de arquivo ".wasm" necess\xe1rio.\n Se voc\xea \xe9 o administrador do servidor, por favor, certifique-se de que o arquivo foi carregado corretamente.\n Se o problema persistir, voc\xea pode precisar usar a configura\xe7\xe3o "publicPath": por favor consulte a wiki do Ruffle para obter ajuda.\nerror-wasm-mime-type =\n Ruffle encontrou um grande problema ao tentar inicializar.\n Este servidor de web n\xe3o est\xe1 servindo ".wasm" arquivos com o tipo MIME correto.\n Se voc\xea \xe9 o administrador do servidor, por favor consulte o wiki do Ruffle para obter ajuda.\nerror-swf-fetch =\n Ruffle falhou ao carregar o arquivo Flash SWF.\n A raz\xe3o prov\xe1vel \xe9 que o arquivo n\xe3o existe mais, ent\xe3o n\xe3o h\xe1 nada para o Ruffle carregar.\n Tente contatar o administrador do site para obter ajuda.\nerror-swf-cors =\n Ruffle falhou ao carregar o arquivo Flash SWF.\n O acesso para fetch provavelmente foi bloqueado pela pol\xedtica CORS.\n Se voc\xea for o administrador do servidor, consulte o wiki do Ruffle para obter ajuda.\nerror-wasm-cors =\n Ruffle falhou ao carregar o componente de arquivo ".wasm" necess\xe1rio.\n O acesso para fetch foi provavelmente bloqueado pela pol\xedtica CORS.\n Se voc\xea \xe9 o administrador do servidor, por favor consulte a wiki do Ruffle para obter ajuda.\nerror-wasm-invalid =\n Ruffle encontrou um grande problema ao tentar inicializar.\n Parece que esta p\xe1gina tem arquivos ausentes ou inv\xe1lidos para executar o Ruffle.\n Se voc\xea for o administrador do servidor, consulte o wiki do Ruffle para obter ajuda.\nerror-wasm-download =\n O Ruffle encontrou um grande problema ao tentar inicializar.\n Muitas vezes isso pode se resolver sozinho, ent\xe3o voc\xea pode tentar recarregar a p\xe1gina.\n Caso contr\xe1rio, contate o administrador do site.\nerror-wasm-disabled-on-edge =\n O Ruffle falhou ao carregar o componente de arquivo ".wasm" necess\xe1rio.\n Para corrigir isso, tente abrir configura\xe7\xf5es do seu navegador, clicando em "Privacidade, pesquisa e servi\xe7os", rolando para baixo e desativando "Melhore sua seguran\xe7a na web".\n Isso permitir\xe1 que seu navegador carregue os arquivos ".wasm" necess\xe1rios.\n Se o problema persistir, talvez seja necess\xe1rio usar um navegador diferente.\nerror-javascript-conflict =\n Ruffle encontrou um grande problema ao tentar inicializar.\n Parece que esta p\xe1gina usa c\xf3digo JavaScript que entra em conflito com o Ruffle.\n Se voc\xea for o administrador do servidor, convidamos voc\xea a tentar carregar o arquivo em uma p\xe1gina em branco.\nerror-javascript-conflict-outdated = Voc\xea tamb\xe9m pode tentar fazer o upload de uma vers\xe3o mais recente do Ruffle que pode contornar o problema (a compila\xe7\xe3o atual est\xe1 desatualizada: { $buildDate }).\nerror-csp-conflict =\n Ruffle encontrou um grande problema ao tentar inicializar.\n A pol\xedtica de seguran\xe7a de conte\xfado deste servidor da web n\xe3o permite a execu\xe7\xe3o do componente ".wasm" necess\xe1rio.\n Se voc\xea for o administrador do servidor, consulte o wiki do Ruffle para obter ajuda.\nerror-unknown =\n O Ruffle encontrou um grande problema enquanto tentava exibir este conte\xfado em Flash.\n { $outdated ->\n [true] Se voc\xea \xe9 o administrador do servidor, por favor tente fazer o upload de uma vers\xe3o mais recente do Ruffle (a compila\xe7\xe3o atual est\xe1 desatualizada: { $buildDate }).\n *[false] Isso n\xe3o deveria acontecer, ent\xe3o apreciar\xedamos muito se voc\xea pudesse arquivar um bug!\n }\n',"save-manager.ftl":"save-delete-prompt = Tem certeza que deseja excluir este arquivo de salvamento?\nsave-reload-prompt =\n A \xfanica maneira de { $action ->\n [delete] excluir\n *[replace] substituir\n } este arquivo sem potencial conflito \xe9 recarregar este conte\xfado. Deseja continuar mesmo assim?\nsave-download = Baixar\nsave-replace = Substituir\nsave-delete = Excluir\nsave-backup-all = Baixar todos os arquivos de salvamento\n","volume-controls.ftl":""},"pt-PT":{"context_menu.ftl":"context-menu-download-swf = Descarga.swf\ncontext-menu-copy-debug-info = Copiar informa\xe7\xf5es de depura\xe7\xe3o\ncontext-menu-open-save-manager = Abrir Gestor de Grava\xe7\xf5es\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] Sobre a extens\xe3o do Ruffle ({ $version })\n *[other] Sobre o Ruffle ({ $version })\n }\ncontext-menu-hide = Esconder este menu\ncontext-menu-exit-fullscreen = Fechar Ecr\xe3 Inteiro\ncontext-menu-enter-fullscreen = Abrir Ecr\xe3 Inteiro\ncontext-menu-volume-controls = Controlos de volume\n","messages.ftl":'message-cant-embed =\n O Ruffle n\xe3o conseguiu abrir o Flash integrado nesta p\xe1gina.\n Para tentar resolver o problema, pode abrir o ficheiro num novo separador.\npanic-title = Algo correu mal :(\nmore-info = Mais informa\xe7\xf5es\nrun-anyway = Executar mesmo assim\ncontinue = Continuar\nreport-bug = Reportar falha\nupdate-ruffle = Atualizar o Ruffle\nruffle-demo = Demonstra\xe7\xe3o na Web\nruffle-desktop = Aplica\xe7\xe3o para Desktop\nruffle-wiki = Ver a Wiki do Ruffle\nenable-hardware-acceleration = Parece que a acelera\xe7\xe3o de hardware n\xe3o est\xe1 ativada. Mesmo que o Ruffle funcione, pode estar excessivamente lento. Descubra como ativar a acelera\xe7\xe3o de hardware seguindo este link.\nview-error-details = Ver detalhes do erro\nopen-in-new-tab = Abrir num novo separador\nclick-to-unmute = Clique para ativar o som\nerror-file-protocol =\n Parece que executa o Ruffle no protocolo "file:".\n Isto n\xe3o funciona, j\xe1 que os navegadores bloqueiam muitas funcionalidades por raz\xf5es de seguran\xe7a.\n Em vez disto, recomendados configurar um servidor local ou usar a demonstra\xe7\xe3o na web, ou a aplica\xe7\xe3o para desktop.\nerror-javascript-config =\n O Ruffle encontrou um problema maior devido a uma configura\xe7\xe3o de JavaScript incorreta.\n Se \xe9 o administrador do servidor, convidamo-lo a verificar os detalhes do erro para descobrir o par\xe2metro problem\xe1tico.\n Pode ainda consultar a wiki do Ruffle para obter ajuda.\nerror-wasm-not-found =\n O Ruffle falhou ao carregar o componente de ficheiro ".wasm" necess\xe1rio.\n Se \xe9 o administrador do servidor, por favor certifique-se de que o ficheiro foi devidamente carregado.\n Se o problema persistir, poder\xe1 querer usar a configura\xe7\xe3o "publicPath": consulte a wiki do Ruffle para obter ajuda.\nerror-wasm-mime-type =\n O Ruffle encontrou um problema maior ao tentar inicializar.\n Este servidor de web n\xe3o suporta ficheiros ".wasm" com o tipo MIME correto.\n Se \xe9 o administrador do servidor, por favor consulte o wiki do Ruffle para obter ajuda.\nerror-swf-fetch =\n Ruffle falhou ao carregar o arquivo SWF do Flash\n A raz\xe3o mais prov\xe1vel \xe9 que o arquivo n\xe3o existe mais, ent\xe3o n\xe3o h\xe1 nada para o Ruffle carregar.\n Tente contactar o administrador do site para obter ajuda.\nerror-swf-cors =\n O Ruffle falhou ao carregar o ficheiro Flash SWF.\n Acesso a buscar foi provavelmente bloqueado pela pol\xedtica de CORS.\n Se \xe9 o administrador do servidor, por favor consulte a wiki do Ruffle para obter ajuda.\nerror-wasm-cors =\n O Ruffle falhou ao carregar o componente de ficheiro ".wasm" necess\xe1rio.\n O acesso a buscar foi provavelmente bloqueado pela pol\xedtica CORS.\n Se \xe9 o administrador do servidor, por favor consulte a wiki do Ruffle para obter ajuda.\nerror-wasm-invalid =\n Ruffle encontrou um grande problema ao tentar inicializar.\n Parece que esta p\xe1gina est\xe1 ausente ou arquivos inv\xe1lidos para executar o Ruffle.\n Se voc\xea \xe9 o administrador do servidor, por favor consulte a wiki do Ruffle para obter ajuda.\nerror-wasm-download =\n O Ruffle encontrou um problema maior ao tentar inicializar.\n Isto frequentemente resolve-se sozinho, portanto experimente recarregar a p\xe1gina.\n Caso contr\xe1rio, por favor contacte o administrador do site.\nerror-wasm-disabled-on-edge =\n O Ruffle falhou ao carregar o componente de ficheiro ".wasm" necess\xe1rio.\n Para corrigir isso, tente abrir as op\xe7\xf5es do seu navegador, clicando em "Privacidade, pesquisa e servi\xe7os", rolando para baixo e desativando "Melhore a sua seguran\xe7a na web".\n Isto permitir\xe1 ao seu navegador carregar os ficheiros ".wasm" necess\xe1rios.\n Se o problema persistir, talvez seja necess\xe1rio usar um navegador diferente.\nerror-javascript-conflict =\n O Ruffle encontrou um problema maior ao tentar inicializar.\n Parece que esta p\xe1gina usa c\xf3digo JavaScript que entra em conflito com o Ruffle.\n Se \xe9 o administrador do servidor, convidamo-lo a tentar carregar o ficheiro em numa p\xe1gina em branco.\nerror-javascript-conflict-outdated = Pode ainda tentar carregar uma vers\xe3o mais recente do Ruffle que talvez contorne o problema (a compila\xe7\xe3o atual est\xe1 desatualizada: { $buildDate }).\nerror-csp-conflict =\n O Ruffle encontrou um problema maior ao tentar inicializar.\n A Pol\xedtica de Seguran\xe7a de Conte\xfado deste servidor n\xe3o permite que o componente ".wasm" necess\xe1rio seja executado.\n Se \xe9 o administrador do servidor, por favor consulte o wiki do Ruffle para obter ajuda.\nerror-unknown =\n O Ruffle encontrou um problema maior enquanto tentava mostrar este conte\xfado em Flash.\n { $outdated ->\n [true] Se \xe9 o administrador do servidor, por favor tente carregar uma vers\xe3o mais recente do Ruffle (a compila\xe7\xe3o atual est\xe1 desatualizada: { $buildDate }).\n *[false] N\xe3o era suposto isto ter acontecido, por isso agradecer\xedamos muito se pudesse reportar a falha!\n }\n',"save-manager.ftl":"save-delete-prompt = Tem a certeza de que quer apagar esta grava\xe7\xe3o?\nsave-reload-prompt =\n A \xfanica forma de { $action ->\n [delete] apagar\n *[replace] substituir\n } esta grava\xe7\xe3o sem um potencial conflito \xe9 recarregar este conte\xfado. Deseja continuar mesmo assim?\nsave-download = Descarregar\nsave-replace = Substituir\nsave-delete = Apagar\nsave-backup-all = Descarregar todas as grava\xe7\xf5es\n","volume-controls.ftl":"volume-controls = Controlos de volume\nvolume-controls-mute = Silenciar\nvolume-controls-volume = Volume\n"},"ro-RO":{"context_menu.ftl":"context-menu-download-swf = Descarc\u0103 .swf\ncontext-menu-copy-debug-info = Copiaz\u0103 informa\u021biile de depanare\ncontext-menu-open-save-manager = Deschide managerul de salv\u0103ri\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] Despre extensia Ruffle ({ $version })\n *[other] Despre Ruffle ({ $version })\n }\ncontext-menu-hide = Ascunde acest meniu\ncontext-menu-exit-fullscreen = Ie\u0219i din ecranul complet\ncontext-menu-enter-fullscreen = Intr\u0103 \xeen ecran complet\n","messages.ftl":'message-cant-embed =\n Ruffle nu a putut rula Flash \xeencorporat \xeen aceast\u0103 pagin\u0103.\n Pute\u021bi \xeencerca s\u0103 deschide\u021bi fi\u0219ierul \xeentr-o fil\u0103 separat\u0103, pentru a evita aceast\u0103 problem\u0103.\npanic-title = Ceva a mers prost :(\nmore-info = Mai multe informa\u021bii\nrun-anyway = Ruleaz\u0103 oricum\ncontinue = Continu\u0103\nreport-bug = Raporteaz\u0103 un bug\nupdate-ruffle = Actualizeaz\u0103 Ruffle\nruffle-demo = Demo web\nruffle-desktop = Aplica\u021bie desktop\nruffle-wiki = Vezi wikiul Ruffle\nview-error-details = Vezi detaliile erorii\nopen-in-new-tab = Deschide \xeentr-o fil\u0103 nou\u0103\nclick-to-unmute = D\u0103 click pentru a dezmu\u021bi\nerror-file-protocol =\n Se pare c\u0103 rulezi Ruffle pe protocolul \u201efile:\u201d.\n Acesta nu func\u021bioneaz\u0103, deoarece browserele blocheaz\u0103 func\u021bionarea multor func\u021bii din motive de securitate.\n \xcen schimb, te invit\u0103m s\u0103 configurezi un server local sau s\u0103 folose\u0219ti fie demoul web, fie aplica\u021bia desktop.\nerror-javascript-config =\n Ruffle a \xeent\xe2mpinat o problem\u0103 major\u0103 din cauza unei configur\u0103ri incorecte a JavaScript.\n Dac\u0103 sunte\u021bi administratorul serverului, v\u0103 invit\u0103m s\u0103 verifica\u021bi detaliile de eroare pentru a afla care parametru este defect.\n Pute\u021bi consulta \u0219i Ruffle wiki pentru ajutor.\nerror-wasm-not-found =\n Ruffle a e\u0219uat la \xeenc\u0103rcarea componentei de fi\u0219ier ".wasm".\n Dac\u0103 sunte\u021bi administratorul serverului, v\u0103 rug\u0103m s\u0103 v\u0103 asigura\u021bi c\u0103 fi\u0219ierul a fost \xeenc\u0103rcat corect.\n Dac\u0103 problema persist\u0103, poate fi necesar s\u0103 utiliza\u0163i setarea "publicPath": v\u0103 rug\u0103m s\u0103 consulta\u0163i Ruffle wiki pentru ajutor.\nerror-wasm-mime-type =\n Ruffle a \xeent\xe2mpinat o problem\u0103 major\u0103 \xeen timp ce se \xeencerca ini\u021bializarea.\n Acest server web nu serve\u0219te ". asm" fi\u0219iere cu tipul corect MIME.\n Dac\u0103 sunte\u021bi administrator de server, v\u0103 rug\u0103m s\u0103 consulta\u021bi Ruffle wiki pentru ajutor.\nerror-swf-fetch =\n Ruffle a e\u0219uat la \xeenc\u0103rcarea fi\u0219ierului Flash SWF.\n Motivul cel mai probabil este c\u0103 fi\u015fierul nu mai exist\u0103, deci nu exist\u0103 nimic pentru Ruffle s\u0103 se \xeencarce.\n \xcencerca\u021bi s\u0103 contacta\u021bi administratorul site-ului web pentru ajutor.\nerror-swf-cors =\n Ruffle a e\u0219uat la \xeenc\u0103rcarea fi\u0219ierului Flash SWF.\n Accesul la preluare a fost probabil blocat de politica CORS.\n Dac\u0103 sunte\u0163i administratorul serverului, v\u0103 rug\u0103m s\u0103 consulta\u0163i Ruffle wiki pentru ajutor.\nerror-wasm-cors =\n Ruffle a e\u0219uat \xeen \xeenc\u0103rcarea componentei de fi\u0219ier ".wasm".\n Accesul la preluare a fost probabil blocat de politica CORS.\n Dac\u0103 sunte\u0163i administratorul serverului, v\u0103 rug\u0103m s\u0103 consulta\u0163i Ruffle wiki pentru ajutor.\nerror-wasm-invalid =\n Ruffle a \xeent\xe2mpinat o problem\u0103 major\u0103 \xeen timp ce se \xeencearc\u0103 ini\u021bializarea.\n Se pare c\u0103 aceast\u0103 pagin\u0103 are fi\u0219iere lips\u0103 sau invalide pentru rularea Ruffle.\n Dac\u0103 sunte\u0163i administratorul serverului, v\u0103 rug\u0103m s\u0103 consulta\u0163i Ruffle wiki pentru ajutor.\nerror-wasm-download =\n Ruffle a \xeent\xe2mpinat o problem\u0103 major\u0103 \xeen timp ce \xeencerca s\u0103 ini\u021bializeze.\n Acest lucru se poate rezolva adesea, astfel \xeenc\xe2t pute\u0163i \xeencerca s\u0103 re\xeenc\u0103rca\u0163i pagina.\n Altfel, v\u0103 rug\u0103m s\u0103 contacta\u0163i administratorul site-ului.\nerror-wasm-disabled-on-edge =\n Ruffle nu a putut \xeenc\u0103rca componenta de fi\u0219ier ".wasm".\n Pentru a remedia acest lucru, \xeencerca\u021bi s\u0103 deschide\u021bi set\u0103rile browser-ului dvs., ap\u0103s\xe2nd pe "Confiden\u021bialitate, c\u0103utare \u0219i servicii", derul\xe2nd \xeen jos \u0219i \xeenchiz\xe2nd "\xcembun\u0103t\u0103\u021be\u0219te-\u021bi securitatea pe web".\n Acest lucru va permite browser-ului s\u0103 \xeencarce fi\u0219ierele ".wasm" necesare.\n Dac\u0103 problema persist\u0103, ar putea fi necesar s\u0103 folosi\u021bi un browser diferit.\nerror-javascript-conflict =\n Ruffle a \xeent\xe2mpinat o problem\u0103 major\u0103 \xeen timp ce \xeencerca s\u0103 ini\u021bializeze.\n Se pare c\u0103 aceast\u0103 pagin\u0103 folose\u0219te codul JavaScript care intr\u0103 \xeen conflict cu Ruffle.\n Dac\u0103 sunte\u0163i administratorul serverului, v\u0103 invit\u0103m s\u0103 \xeenc\u0103rca\u0163i fi\u015fierul pe o pagin\u0103 goal\u0103.\nerror-javascript-conflict-outdated = De asemenea, po\u021bi \xeencerca s\u0103 \xeencarci o versiune mai recent\u0103 de Ruffle care poate ocoli problema (versiunea curent\u0103 este expirat\u0103: { $buildDate }).\nerror-csp-conflict =\n Ruffle a \xeent\xe2mpinat o problem\u0103 major\u0103 \xeen timp ce se \xeencerca ini\u021bializarea.\n Politica de securitate a con\u021binutului acestui server web nu permite serviciul necesar". asm" component\u0103 pentru a rula.\n Dac\u0103 sunte\u021bi administratorul de server, consulta\u021bi Ruffle wiki pentru ajutor.\nerror-unknown =\n Ruffle a \xeent\xe2mpinat o problem\u0103 major\u0103 \xeen timp ce \xeencerca s\u0103 afi\u0219eze acest con\u021binut Flash.\n { $outdated ->\n [true] Dac\u0103 e\u0219ti administratorul serverului, te rug\u0103m s\u0103 \xeencerci s\u0103 \xeencarci o versiune mai recent\u0103 de Ruffle (versiunea actual\u0103 este dep\u0103\u015fit\u0103: { $buildDate }).\n *[false] Acest lucru nu ar trebui s\u0103 se \xeent\xe2mple, a\u0219a c\u0103 am aprecia foarte mult dac\u0103 ai putea trimite un bug!\n }\n',"save-manager.ftl":"save-delete-prompt = Sigur vrei s\u0103 \u0219tergi acest fi\u0219ier de salvare?\nsave-reload-prompt =\n Singura cale de a { $action ->\n [delete] \u0219terge\n *[replace] \xeenlocui\n } acest fi\u0219ier de salvare f\u0103r\u0103 un conflict poten\u021bial este de a re\xeenc\u0103rca acest con\u021binut. Dore\u0219ti s\u0103 continui oricum?\nsave-download = Descarc\u0103\nsave-replace = \xcenlocuie\u0219te\nsave-delete = \u0218terge\n","volume-controls.ftl":"volume-controls = Comenzi pentru volum\n"},"ru-RU":{"context_menu.ftl":"context-menu-download-swf = \u0421\u043a\u0430\u0447\u0430\u0442\u044c .swf\ncontext-menu-copy-debug-info = \u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e\ncontext-menu-open-save-manager = \u041c\u0435\u043d\u0435\u0434\u0436\u0435\u0440 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0439\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] \u041e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0438 Ruffle ({ $version })\n *[other] \u041e Ruffle ({ $version })\n }\ncontext-menu-hide = \u0421\u043a\u0440\u044b\u0442\u044c \u044d\u0442\u043e \u043c\u0435\u043d\u044e\ncontext-menu-exit-fullscreen = \u041e\u043a\u043e\u043d\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c\ncontext-menu-enter-fullscreen = \u041f\u043e\u043b\u043d\u043e\u044d\u043a\u0440\u0430\u043d\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c\ncontext-menu-volume-controls = \u0413\u0440\u043e\u043c\u043a\u043e\u0441\u0442\u044c\n","messages.ftl":'message-cant-embed =\n Ruffle \u043d\u0435 \u0441\u043c\u043e\u0433 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Flash, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u043d\u0430 \u044d\u0442\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.\n \u0427\u0442\u043e\u0431\u044b \u043e\u0431\u043e\u0439\u0442\u0438 \u044d\u0442\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0444\u0430\u0439\u043b \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0432\u043a\u043b\u0430\u0434\u043a\u0435.\npanic-title = \u0427\u0442\u043e-\u0442\u043e \u043f\u043e\u0448\u043b\u043e \u043d\u0435 \u0442\u0430\u043a :(\nmore-info = \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435\nrun-anyway = \u0412\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\ncontinue = \u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c\nreport-bug = \u0421\u043e\u043e\u0431\u0449\u0438\u0442\u044c \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435\nupdate-ruffle = \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c Ruffle\nruffle-demo = \u0412\u0435\u0431-\u0434\u0435\u043c\u043e\nruffle-desktop = \u041d\u0430\u0441\u0442\u043e\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\nruffle-wiki = \u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0432\u0438\u043a\u0438 Ruffle\nenable-hardware-acceleration = \u041f\u043e\u0445\u043e\u0436\u0435, \u0447\u0442\u043e \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u043e\u0435 \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0435 \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e. \u0425\u043e\u0442\u044c Ruffle \u0438 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u043e\u043f\u0440\u0430\u0432\u0434\u0430\u043d\u043d\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u043c. \u041e \u0442\u043e\u043c, \u043a\u0430\u043a \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u043e\u0435 \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0435, \u043c\u043e\u0436\u043d\u043e \u0443\u0437\u043d\u0430\u0442\u044c, \u043f\u0435\u0440\u0435\u0439\u0434\u044f \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435.\nview-error-details = \u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435\nopen-in-new-tab = \u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0432 \u043d\u043e\u0432\u043e\u0439 \u0432\u043a\u043b\u0430\u0434\u043a\u0435\nclick-to-unmute = \u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0437\u0432\u0443\u043a\nerror-file-protocol =\n \u041f\u043e\u0445\u043e\u0436\u0435, \u0447\u0442\u043e \u0432\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0435 Ruffle \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 "file:".\n \u042d\u0442\u043e \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u043c\u043d\u043e\u0433\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043f\u043e \u0441\u043e\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u043c \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438.\n \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c \u0432\u0430\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0432\u0435\u0431-\u0434\u0435\u043c\u043e \u0438\u043b\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440.\nerror-javascript-config =\n \u0412\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430 \u0438\u0437-\u0437\u0430 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 JavaScript.\n \u0415\u0441\u043b\u0438 \u0432\u044b \u044f\u0432\u043b\u044f\u0435\u0442\u0435\u0441\u044c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043c\u044b \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c \u0432\u0430\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0434\u0435\u0442\u0430\u043b\u0438 \u043e\u0448\u0438\u0431\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u044f\u0441\u043d\u0438\u0442\u044c, \u043a\u0430\u043a\u043e\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0434\u0430\u043b \u0441\u0431\u043e\u0439.\n \u0412\u044b \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u0437\u0430 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a \u0432\u0438\u043a\u0438 Ruffle.\nerror-wasm-not-found =\n Ruffle \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0444\u0430\u0439\u043b\u0430 ".wasm".\n \u0415\u0441\u043b\u0438 \u0432\u044b \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0444\u0430\u0439\u043b \u0431\u044b\u043b \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e.\n \u0415\u0441\u043b\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043d\u0435 \u0443\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f, \u0432\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 "publicPath": \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044c \u043a \u0432\u0438\u043a\u0438 Ruffle.\nerror-wasm-mime-type =\n Ruffle \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.\n \u042d\u0442\u043e\u0442 \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0444\u0430\u0439\u043b\u044b ".wasm" \u0441 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u043c \u0442\u0438\u043f\u043e\u043c MIME.\n \u0415\u0441\u043b\u0438 \u0432\u044b \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044c \u0437\u0430 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a \u0432\u0438\u043a\u0438 Ruffle.\nerror-swf-fetch =\n Ruffle \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c SWF-\u0444\u0430\u0439\u043b Flash.\n \u0412\u0435\u0440\u043e\u044f\u0442\u043d\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0444\u0430\u0439\u043b \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 Ruffle \u043d\u0435\u0447\u0435\u0433\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c.\n \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0441\u0432\u044f\u0437\u0430\u0442\u044c\u0441\u044f \u0441 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c \u0441\u0430\u0439\u0442\u0430 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043c\u043e\u0449\u0438.\nerror-swf-cors =\n Ruffle \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c SWF-\u0444\u0430\u0439\u043b Flash.\n \u0421\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0444\u0430\u0439\u043b\u0443 \u0431\u044b\u043b \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u043e\u0439 CORS.\n \u0415\u0441\u043b\u0438 \u0432\u044b \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044c \u0437\u0430 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a \u0432\u0438\u043a\u0438 Ruffle.\nerror-wasm-cors =\n Ruffle \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0444\u0430\u0439\u043b\u0430 ".wasm".\n \u0421\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0444\u0430\u0439\u043b\u0443 \u0431\u044b\u043b \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u043e\u0439 CORS.\n \u0415\u0441\u043b\u0438 \u0432\u044b \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044c \u0437\u0430 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a \u0432\u0438\u043a\u0438 Ruffle.\nerror-wasm-invalid =\n Ruffle \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.\n \u041f\u043e\u0445\u043e\u0436\u0435, \u0447\u0442\u043e \u043d\u0430 \u044d\u0442\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0444\u0430\u0439\u043b\u044b \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 Ruffle \u0438\u043b\u0438 \u043e\u043d\u0438 \u043d\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b.\n \u0415\u0441\u043b\u0438 \u0432\u044b \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044c \u0437\u0430 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a \u0432\u0438\u043a\u0438 Ruffle.\nerror-wasm-download =\n Ruffle \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.\n \u0427\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u044d\u0442\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0443\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0441\u0430\u043c\u0430 \u0441\u043e\u0431\u043e\u044e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443.\n \u0415\u0441\u043b\u0438 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442 \u043f\u043e\u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f, \u0441\u0432\u044f\u0436\u0438\u0442\u0435\u0441\u044c \u0441 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c \u0441\u0430\u0439\u0442\u0430.\nerror-wasm-disabled-on-edge =\n Ruffle \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0444\u0430\u0439\u043b\u0430 ".wasm".\n \u0427\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u0443 \u043e\u0448\u0438\u0431\u043a\u0443, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0434\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 WASM-\u0444\u0430\u0439\u043b\u044b.\n \u0415\u0441\u043b\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043e\u0441\u0442\u0430\u043b\u0430\u0441\u044c, \u0432\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u0440\u0443\u0433\u043e\u0439 \u0431\u0440\u0430\u0443\u0437\u0435\u0440.\nerror-javascript-conflict =\n Ruffle \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.\n \u041f\u043e\u0445\u043e\u0436\u0435, \u0447\u0442\u043e \u044d\u0442\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u0443\u044e\u0449\u0438\u0439 \u0441 Ruffle \u043a\u043e\u0434 JavaScript.\n \u0415\u0441\u043b\u0438 \u0432\u044b \u044f\u0432\u043b\u044f\u0435\u0442\u0435\u0441\u044c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043c\u044b \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c \u0432\u0430\u043c \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0444\u0430\u0439\u043b \u043d\u0430 \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.\nerror-javascript-conflict-outdated = \u0412\u044b \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0432\u0435\u0440\u0441\u0438\u044e Ruffle, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u043e\u0439\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 (\u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0443\u0441\u0442\u0430\u0440\u0435\u043b\u0430: { $buildDate }).\nerror-csp-conflict =\n Ruffle \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.\n \u041f\u043e\u043b\u0438\u0442\u0438\u043a\u0430 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u044d\u0442\u043e\u0433\u043e \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 ".wasm".\n \u0415\u0441\u043b\u0438 \u0432\u044b \u044f\u0432\u043b\u044f\u0435\u0442\u0435\u0441\u044c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044c \u0437\u0430 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a \u0432\u0438\u043a\u0438 Ruffle.\nerror-unknown =\n Ruffle \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u044d\u0442\u043e\u0442 Flash-\u043a\u043e\u043d\u0442\u0435\u043d\u0442.\n { $outdated ->\n [true] \u0415\u0441\u043b\u0438 \u0432\u044b \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043d\u043e\u0432\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e Ruffle (\u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0443\u0441\u0442\u0430\u0440\u0435\u043b\u0430: { $buildDate }).\n *[false] \u042d\u0442\u043e\u0433\u043e \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u0438\u0437\u043d\u0430\u0442\u0435\u043b\u044c\u043d\u044b, \u0435\u0441\u043b\u0438 \u0432\u044b \u0441\u043e\u043e\u0431\u0449\u0438\u0442\u0435 \u043d\u0430\u043c \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435!\n }\n',"save-manager.ftl":"save-delete-prompt = \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f?\nsave-reload-prompt =\n \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 { $action ->\n [delete] \u0443\u0434\u0430\u043b\u0438\u0442\u044c\n *[replace] \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c\n } \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0431\u0435\u0437 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u0430 \u2013 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442. \u0412\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c?\nsave-download = \u0421\u043a\u0430\u0447\u0430\u0442\u044c\nsave-replace = \u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c\nsave-delete = \u0423\u0434\u0430\u043b\u0438\u0442\u044c\nsave-backup-all = \u0421\u043a\u0430\u0447\u0430\u0442\u044c \u0432\u0441\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f\n","volume-controls.ftl":"volume-controls = \u0420\u0435\u0433\u0443\u043b\u0438\u0440\u043e\u0432\u043a\u0430 \u0433\u0440\u043e\u043c\u043a\u043e\u0441\u0442\u0438\nvolume-controls-mute = \u0411\u0435\u0437 \u0437\u0432\u0443\u043a\u0430\nvolume-controls-volume = \u0413\u0440\u043e\u043c\u043a\u043e\u0441\u0442\u044c\n"},"sk-SK":{"context_menu.ftl":"context-menu-download-swf = Stiahnu\u0165 .swf\ncontext-menu-copy-debug-info = Skop\xedrova\u0165 debug info\ncontext-menu-open-save-manager = Otvori\u0165 spr\xe1vcu ulo\u017een\xed\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] O Ruffle roz\u0161\xedren\xed ({ $version })\n *[other] O Ruffle ({ $version })\n }\ncontext-menu-hide = Skry\u0165 menu\ncontext-menu-exit-fullscreen = Ukon\u010di\u0165 re\u017eim celej obrazovky\ncontext-menu-enter-fullscreen = Prejs\u0165 do re\u017eimu celej obrazovky\ncontext-menu-volume-controls = Ovl\xe1danie hlasitosti\n","messages.ftl":'message-cant-embed =\n Ruffle nemohol spusti\u0165 Flash vlo\u017een\xfd na tejto str\xe1nke.\n M\xf4\u017eete sa pok\xfasi\u0165 otvori\u0165 s\xfabor na samostatnej karte, aby ste sa vyhli tomuto probl\xe9mu.\npanic-title = Nie\u010do sa pokazilo :(\nmore-info = Viac inform\xe1ci\xed\nrun-anyway = Spusti\u0165 aj tak\ncontinue = Pokra\u010dova\u0165\nreport-bug = Nahl\xe1si\u0165 chybu\nupdate-ruffle = Aktualizova\u0165 Ruffle\nruffle-demo = Web Demo\nruffle-desktop = Desktopov\xe1 aplik\xe1cia\nruffle-wiki = Zobrazi\u0165 Ruffle Wiki\nenable-hardware-acceleration = Zd\xe1 sa, \u017ee hardv\xe9rov\xe1 akceler\xe1cia nie je povolen\xe1. Aj ke\u010f Ruffle funguje spr\xe1vne, m\xf4\u017ee by\u0165 neprimerane pomal\xfd. Ako povoli\u0165 hardv\xe9rov\xfa akceler\xe1ciu zist\xedte na tomto odkaze.\nview-error-details = Zobrazi\u0165 podrobnosti o chybe\nopen-in-new-tab = Otvori\u0165 na novej karte\nclick-to-unmute = Kliknut\xedm zapnete zvuk\nerror-file-protocol =\n Zd\xe1 sa, \u017ee pou\u017e\xedvate Ruffle na protokole "file:".\n To nie je mo\u017en\xe9, preto\u017ee prehliada\u010de blokuj\xfa fungovanie mnoh\xfdch funkci\xed z bezpe\u010dnostn\xfdch d\xf4vodov.\n Namiesto toho v\xe1m odpor\xfa\u010dame nastavi\u0165 lok\xe1lny server alebo pou\u017ei\u0165 web demo \u010di desktopov\xfa aplik\xe1ciu.\nerror-javascript-config =\n Ruffle narazil na probl\xe9m v d\xf4sledku nespr\xe1vnej konfigur\xe1cie JavaScriptu.\n Ak ste spr\xe1vcom servera, odpor\xfa\u010dame v\xe1m skontrolova\u0165 podrobnosti o chybe, aby ste zistili, ktor\xfd parameter je chybn\xfd.\n Pomoc m\xf4\u017eete z\xedska\u0165 aj na wiki Ruffle.\nerror-wasm-not-found =\n Ruffle sa nepodarilo na\u010d\xedta\u0165 po\u017eadovan\xfd komponent s\xfaboru \u201e.wasm\u201c.\n Ak ste spr\xe1vcom servera, skontrolujte, \u010di bol s\xfabor spr\xe1vne nahran\xfd.\n Ak probl\xe9m pretrv\xe1va, mo\u017eno budete musie\u0165 pou\u017ei\u0165 nastavenie \u201epublicPath\u201c: pomoc n\xe1jdete na wiki Ruffle.\nerror-wasm-mime-type =\n Ruffle narazil na probl\xe9m pri pokuse o inicializ\xe1ciu.\n Tento webov\xfd server neposkytuje s\xfabory \u201e.wasm\u201c so spr\xe1vnym typom MIME.\n Ak ste spr\xe1vcom servera, pomoc n\xe1jdete na Ruffle wiki.\nerror-swf-fetch =\n Ruffle sa nepodarilo na\u010d\xedta\u0165 SWF s\xfabor Flash.\n Najpravdepodobnej\u0161\xedm d\xf4vodom je, \u017ee s\xfabor u\u017e neexistuje, tak\u017ee Ruffle nem\xe1 \u010do na\u010d\xedta\u0165.\n Sk\xfaste po\u017eiada\u0165 o pomoc spr\xe1vcu webovej lokality.\nerror-swf-cors =\n Ruffle sa nepodarilo na\u010d\xedta\u0165 SWF s\xfabor Flash.\n Pr\xedstup k na\u010d\xedtaniu bol pravdepodobne zablokovan\xfd politikou CORS.\n Ak ste spr\xe1vcom servera, pomoc n\xe1jdete na Ruffle wiki.\nerror-wasm-cors =\n Ruffle sa nepodarilo na\u010d\xedta\u0165 po\u017eadovan\xfd komponent s\xfaboru \u201e.wasm\u201c.\n Pr\xedstup k na\u010d\xedtaniu bol pravdepodobne zablokovan\xfd politikou CORS.\n Ak ste spr\xe1vcom servera, pomoc n\xe1jdete na Ruffle wiki.\nerror-wasm-invalid =\n Ruffle narazil na probl\xe9m pri pokuse o inicializ\xe1ciu.\n Zd\xe1 sa, \u017ee na tejto str\xe1nke ch\xfdbaj\xfa alebo s\xfa neplatn\xe9 s\xfabory na spustenie Ruffle.\n Ak ste spr\xe1vcom servera, pomoc n\xe1jdete na Ruffle wiki.\nerror-wasm-download =\n Ruffle narazil na probl\xe9m pri pokuse o inicializ\xe1ciu.\n Probl\xe9m sa m\xf4\u017ee vyrie\u0161i\u0165 aj s\xe1m, tak\u017ee m\xf4\u017eete sk\xfasi\u0165 str\xe1nku na\u010d\xedta\u0165 znova.\n V opa\u010dnom pr\xedpade kontaktujte administr\xe1tora str\xe1nky.\nerror-wasm-disabled-on-edge =\n Ruffle sa nepodarilo na\u010d\xedta\u0165 po\u017eadovan\xfd komponent s\xfaboru \u201e.wasm\u201c.\n Ak chcete tento probl\xe9m vyrie\u0161i\u0165, sk\xfaste otvori\u0165 nastavenia prehliada\u010da, kliknite na polo\u017eku \u201eOchrana osobn\xfdch \xfadajov, vyh\u013ead\xe1vanie a slu\u017eby\u201c, prejdite nadol a vypnite mo\u017enos\u0165 \u201eZv\xfd\u0161te svoju bezpe\u010dnos\u0165 na webe\u201c.\n V\xe1\u0161mu prehliada\u010du to umo\u017en\xed na\u010d\xedta\u0165 po\u017eadovan\xe9 s\xfabory \u201e.wasm\u201c.\n Ak probl\xe9m pretrv\xe1va, mo\u017eno budete musie\u0165 pou\u017ei\u0165 in\xfd prehliada\u010d.\nerror-javascript-conflict =\n Ruffle narazil na probl\xe9m pri pokuse o inicializ\xe1ciu.\n Zd\xe1 sa, \u017ee t\xe1to str\xe1nka pou\u017e\xedva k\xf3d JavaScript, ktor\xfd je v konflikte s Ruffle.\n Ak ste spr\xe1vcom servera, odpor\xfa\u010dame v\xe1m sk\xfasi\u0165 na\u010d\xedta\u0165 s\xfabor na pr\xe1zdnu str\xe1nku.\nerror-javascript-conflict-outdated = M\xf4\u017eete sa tie\u017e pok\xfasi\u0165 nahra\u0165 nov\u0161iu verziu Ruffle, ktor\xe1 m\xf4\u017ee dan\xfd probl\xe9m vyrie\u0161i\u0165 (aktu\xe1lny build je zastaran\xfd: { $buildDate }).\nerror-csp-conflict =\n Ruffle narazil na probl\xe9m pri pokuse o inicializ\xe1ciu.\n Z\xe1sady zabezpe\u010denia obsahu tohto webov\xe9ho servera nepovo\u013euj\xfa spustenie po\u017eadovan\xe9ho komponentu \u201e.wasm\u201c.\n Ak ste spr\xe1vcom servera, pomoc n\xe1jdete na Ruffle wiki.\nerror-unknown =\n Ruffle narazil na probl\xe9m pri pokuse zobrazi\u0165 tento Flash obsah.\n { $outdated ->\n [true] Ak ste spr\xe1vcom servera, sk\xfaste nahra\u0165 nov\u0161iu verziu Ruffle (aktu\xe1lny build je zastaran\xfd: { $buildDate }).\n *[false] Toto by sa nemalo sta\u0165, tak\u017ee by sme naozaj ocenili, keby ste mohli nahl\xe1si\u0165 chybu!\n }\n',"save-manager.ftl":"save-delete-prompt = Naozaj chcete odstr\xe1ni\u0165 tento s\xfabor s ulo\u017een\xfdmi poz\xedciami?\nsave-reload-prompt =\n Jedin\xfd sp\xf4sob, ako { $action ->\n [delete] vymaza\u0165\n *[replace] nahradi\u0165\n } tento s\xfabor s ulo\u017een\xfdmi poz\xedciami bez potenci\xe1lneho konfliktu je op\xe4tovn\xe9 na\u010d\xedtanie tohto obsahu. Chcete napriek tomu pokra\u010dova\u0165?\nsave-download = Stiahnu\u0165\nsave-replace = Nahradi\u0165\nsave-delete = Vymaza\u0165\nsave-backup-all = Stiahnu\u0165 v\u0161etky s\xfabory s ulo\u017een\xfdmi poz\xedciami\n","volume-controls.ftl":"volume-controls = Ovl\xe1danie hlasitosti\nvolume-controls-mute = Stlmi\u0165\nvolume-controls-volume = Hlasitos\u0165\n"},"sv-SE":{"context_menu.ftl":"context-menu-download-swf = Ladda ner .swf\ncontext-menu-copy-debug-info = Kopiera fels\xf6kningsinfo\ncontext-menu-open-save-manager = \xd6ppna Sparhanteraren\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] Om Ruffle-till\xe4gget ({ $version })\n *[other] Om Ruffle ({ $version })\n }\ncontext-menu-hide = D\xf6lj denna meny\ncontext-menu-exit-fullscreen = Avsluta helsk\xe4rm\ncontext-menu-enter-fullscreen = Helsk\xe4rm\ncontext-menu-volume-controls = Ljudkontroller\n","messages.ftl":'message-cant-embed =\n Ruffle kunde inte k\xf6ra det inb\xe4ddade Flashinneh\xe5llet p\xe5 denna sida.\n Du kan f\xf6rs\xf6ka \xf6ppna filen i en separat flik f\xf6r att kringg\xe5 problemet.\npanic-title = N\xe5got gick fel :(\nmore-info = Mer info\nrun-anyway = K\xf6r \xe4nd\xe5\ncontinue = Forts\xe4tt\nreport-bug = Rapportera Bugg\nupdate-ruffle = Uppdatera Ruffle\nruffle-demo = Webbdemo\nruffle-desktop = Skrivbordsprogram\nruffle-wiki = Se Ruffle-wiki\nenable-hardware-acceleration = Det verkar som att h\xe5rdvaruacceleration inte \xe4r p\xe5. Ruffle kan fortfarande fungera men kan vara orimligt l\xe5ngsam. Du kan ta reda p\xe5 hur man s\xe4tter p\xe5 h\xe5rdvaruacceleration genom att f\xf6lja denna l\xe4nk.\nview-error-details = Visa Felinformation\nopen-in-new-tab = \xd6ppna i en ny flik\nclick-to-unmute = Klicka f\xf6r ljud\nerror-file-protocol =\n Det verkar som att du k\xf6r Ruffle p\xe5 "fil:"-protokollet.\n Detta fungerar inte eftersom webbl\xe4sare blockerar m\xe5nga funktioner fr\xe5n att fungera av s\xe4kerhetssk\xe4l.\n Ist\xe4llet bjuder vi in dig att s\xe4tta upp en lokal server eller antingen anv\xe4nda webbdemon eller skrivbordsprogrammet.\nerror-javascript-config =\n Ruffle har st\xf6tt p\xe5 ett stort fel p\xe5 grund av en felaktig JavaScript-konfiguration.\n Om du \xe4r serveradministrat\xf6ren bjuder vi in dig att kontrollera feldetaljerna f\xf6r att ta reda p\xe5 vilken parameter som \xe4r felaktig.\n Du kan ocks\xe5 konsultera Ruffle-wikin f\xf6r hj\xe4lp.\nerror-wasm-not-found =\n Ruffle misslyckades ladda ".wasm"-filkomponenten.\n Om du \xe4r serveradministrat\xf6ren se till att filen har laddats upp korrekt.\n Om problemet kvarst\xe5r kan du beh\xf6va anv\xe4nda inst\xe4llningen "publicPath": konsultera v\xe4nligen Ruffle-wikin f\xf6r hj\xe4lp.\nerror-wasm-mime-type =\n Ruffle har st\xf6tt p\xe5 ett stort fel under initialiseringen.\n Denna webbserver serverar inte ".wasm"-filer med korrekt MIME-typ.\n Om du \xe4r serveradministrat\xf6ren konsultera v\xe4nligen Ruffle-wikin f\xf6r hj\xe4lp.\nerror-swf-fetch =\n Ruffle misslyckades ladda SWF-filen.\n Det mest sannolika sk\xe4let \xe4r att filen inte l\xe4ngre existerar, s\xe5 det finns inget f\xf6r Ruffle att k\xf6ra.\n F\xf6rs\xf6k att kontakta webbplatsadministrat\xf6ren f\xf6r hj\xe4lp.\nerror-swf-cors =\n Ruffle misslyckades ladda SWF-filen.\n \xc5tkomst att h\xe4mta har sannolikt blockerats av CORS-policy.\n Om du \xe4r serveradministrat\xf6ren konsultera v\xe4nligen Ruffle-wikin f\xf6r hj\xe4lp.\nerror-wasm-cors =\n Ruffle misslyckades ladda ".wasm"-filkomponenten.\n \xc5tkomst att h\xe4mta har sannolikt blockerats av CORS-policy.\n Om du \xe4r serveradministrat\xf6ren konsultera v\xe4nligen Ruffle-wikin f\xf6r hj\xe4lp.\nerror-wasm-invalid =\n Ruffle har st\xf6tt p\xe5 ett stort fel under initialiseringen.\n Det verkar som att den h\xe4r sidan har saknade eller ogiltiga filer f\xf6r att k\xf6ra Ruffle.\n Om du \xe4r serveradministrat\xf6ren konsultera v\xe4nligen Ruffle-wikin f\xf6r hj\xe4lp.\nerror-wasm-download =\n Ruffle har st\xf6tt p\xe5 ett stort fel under initialiseringen.\n Detta kan ofta l\xf6sas av sig sj\xe4lv s\xe5 du kan prova att ladda om sidan.\n Kontakta annars v\xe4nligen webbplatsens administrat\xf6r.\nerror-wasm-disabled-on-edge =\n Ruffle misslyckades ladda ".wasm"-filkomponenten.\n F\xf6r att \xe5tg\xe4rda detta f\xf6rs\xf6k att \xf6ppna webbl\xe4sarens inst\xe4llningar, klicka p\xe5 "Sekretess, s\xf6kning och tj\xe4nster", bl\xe4ddra ner och st\xe4ng av "F\xf6rb\xe4ttra s\xe4kerheten p\xe5 webben".\n Detta till\xe5ter din webbl\xe4sare ladda ".wasm"-filerna.\n Om problemet kvarst\xe5r kan du beh\xf6va anv\xe4nda en annan webbl\xe4sare.\nerror-javascript-conflict =\n Ruffle har st\xf6tt p\xe5 ett stort fel under initialiseringen.\n Det verkar som att den h\xe4r sidan anv\xe4nder JavaScript-kod som st\xf6r Ruffle.\n Om du \xe4r serveradministrat\xf6ren bjuder vi in dig att f\xf6rs\xf6ka k\xf6ra filen p\xe5 en blank sida.\nerror-javascript-conflict-outdated = Du kan ocks\xe5 f\xf6rs\xf6ka ladda upp en nyare version av Ruffle, vilket kan kringg\xe5 problemet (nuvarande version \xe4r utdaterad: { $buildDate }).\nerror-csp-conflict =\n Ruffle har st\xf6tt p\xe5 ett stort fel under initialiseringen.\n Denna webbservers Content Security Policy till\xe5ter inte ".wasm"-komponenten att k\xf6ra.\n Om du \xe4r serveradministrat\xf6ren konsultera v\xe4nligen Ruffle-wikin f\xf6r hj\xe4lp.\nerror-unknown =\n Ruffle har st\xf6tt p\xe5 ett stort fel medan den f\xf6rs\xf6kte visa Flashinneh\xe5llet.\n { $outdated ->\n [true] Om du \xe4r serveradministrat\xf6ren f\xf6rs\xf6k att ladda upp en nyare version av Ruffle (nuvarande version \xe4r utdaterad: { $buildDate }).\n *[false] Detta \xe4r inte t\xe4nkt att h\xe4nda s\xe5 vi skulle verkligen uppskatta om du kunde rapportera in en bugg!\n }\n',"save-manager.ftl":"save-delete-prompt = \xc4r du s\xe4ker p\xe5 att du vill radera sparfilen?\nsave-reload-prompt =\n Det enda s\xe4ttet att { $action ->\n [delete] radera\n *[replace] ers\xe4tta\n } denna sparfil utan potentiell konflikt \xe4r att ladda om inneh\xe5llet. Vill du forts\xe4tta \xe4nd\xe5?\nsave-download = Ladda ner\nsave-replace = Ers\xe4tt\nsave-delete = Radera\nsave-backup-all = Ladda ner alla sparfiler\n","volume-controls.ftl":"volume-controls = Ljudkontroller\nvolume-controls-mute = St\xe4ng av ljud\nvolume-controls-volume = Volym\n"},"tr-TR":{"context_menu.ftl":"context-menu-download-swf = \u0130ndir .swf\ncontext-menu-copy-debug-info = Hata ay\u0131klama bilgisini kopyala\ncontext-menu-open-save-manager = Kay\u0131t Y\xf6neticisini A\xe7\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] Ruffle Uzant\u0131s\u0131 Hakk\u0131nda ({ $version })\n *[other] Ruffle Hakk\u0131nda ({ $version })\n }\ncontext-menu-hide = Bu men\xfcy\xfc gizle\ncontext-menu-exit-fullscreen = Tam ekrandan \xe7\u0131k\ncontext-menu-enter-fullscreen = Tam ekran yap\ncontext-menu-volume-controls = Ses kontrolleri\n","messages.ftl":'message-cant-embed =\n Ruffle, bu sayfaya g\xf6m\xfcl\xfc Flash\'\u0131 \xe7al\u0131\u015ft\u0131ramad\u0131.\n Bu sorunu ortadan kald\u0131rmak i\xe7in dosyay\u0131 ayr\u0131 bir sekmede a\xe7may\u0131 deneyebilirsiniz.\npanic-title = Bir \u015feyler yanl\u0131\u015f gitti :(\nmore-info = Daha fazla bilgi\nrun-anyway = Yine de \xe7al\u0131\u015ft\u0131r\ncontinue = Devam et\nreport-bug = Hata Bildir\nupdate-ruffle = Ruffle\'\u0131 G\xfcncelle\nruffle-demo = A\u011f Demosu\nruffle-desktop = Masa\xfcst\xfc Uygulamas\u0131\nruffle-wiki = Ruffle Wiki\'yi G\xf6r\xfcnt\xfcle\nenable-hardware-acceleration = G\xf6r\xfcn\xfc\u015fe g\xf6re donan\u0131m h\u0131zland\u0131rma etkin de\u011fil. Ruffle \xe7al\u0131\u015fabilir ancak fazlas\u0131yla yava\u015f olabilir. Donan\u0131m h\u0131zland\u0131rmay\u0131 nas\u0131l etkinle\u015ftirebilice\u011finiz hakk\u0131nda bu linkten bilgi alabilirsiniz.\nview-error-details = Hata Ayr\u0131nt\u0131lar\u0131n\u0131 G\xf6r\xfcnt\xfcle\nopen-in-new-tab = Yeni sekmede a\xe7\nclick-to-unmute = Sesi a\xe7mak i\xe7in t\u0131klay\u0131n\nerror-file-protocol =\n G\xf6r\xfcn\xfc\u015fe g\xf6re Ruffle\'\u0131 "dosya:" protokol\xfcnde \xe7al\u0131\u015ft\u0131r\u0131yorsunuz.\n Taray\u0131c\u0131lar g\xfcvenlik nedenleriyle bir\xe7ok \xf6zelli\u011fin \xe7al\u0131\u015fmas\u0131n\u0131 engelledi\u011finden bu i\u015fe yaramaz.\n Bunun yerine, sizi yerel bir sunucu kurmaya veya a\u011f\u0131n demosunu ya da masa\xfcst\xfc uygulamas\u0131n\u0131 kullanmaya davet ediyoruz.\nerror-javascript-config =\n Ruffle, yanl\u0131\u015f bir JavaScript yap\u0131land\u0131rmas\u0131 nedeniyle \xf6nemli bir sorunla kar\u015f\u0131la\u015ft\u0131.\n Sunucu y\xf6neticisiyseniz, hangi parametrenin hatal\u0131 oldu\u011funu bulmak i\xe7in sizi hata ayr\u0131nt\u0131lar\u0131n\u0131 kontrol etmeye davet ediyoruz.\n Yard\u0131m i\xe7in Ruffle wiki\'sine de ba\u015fvurabilirsiniz.\nerror-wasm-not-found =\n Ruffle gerekli ".wasm" dosya bile\u015fenini y\xfckleyemedi.\n Sunucu y\xf6neticisi iseniz, l\xfctfen dosyan\u0131n do\u011fru bir \u015fekilde y\xfcklendi\u011finden emin olun.\n Sorun devam ederse, "publicPath" ayar\u0131n\u0131 kullanman\u0131z gerekebilir: yard\u0131m i\xe7in l\xfctfen Ruffle wiki\'sine ba\u015fvurun.\nerror-wasm-mime-type =\n Ruffle, ba\u015flatmaya \xe7al\u0131\u015f\u0131rken \xf6nemli bir sorunla kar\u015f\u0131la\u015ft\u0131.\n Bu web sunucusu, do\u011fru MIME tipinde ".wasm" dosyalar\u0131 sunmuyor.\n Sunucu y\xf6neticisiyseniz, yard\u0131m i\xe7in l\xfctfen Ruffle wiki\'sine ba\u015fvurun.\nerror-swf-fetch =\n Ruffle, Flash SWF dosyas\u0131n\u0131 y\xfckleyemedi.\n Bunun en olas\u0131 nedeni, dosyan\u0131n art\u0131k mevcut olmamas\u0131 ve bu nedenle Ruffle\'\u0131n y\xfckleyece\u011fi hi\xe7bir \u015feyin olmamas\u0131d\u0131r.\n Yard\u0131m i\xe7in web sitesi y\xf6neticisiyle ileti\u015fime ge\xe7meyi deneyin.\nerror-swf-cors =\n Ruffle, Flash SWF dosyas\u0131n\u0131 y\xfckleyemedi.\n Getirme eri\u015fimi muhtemelen CORS politikas\u0131 taraf\u0131ndan engellenmi\u015ftir.\n Sunucu y\xf6neticisiyseniz, yard\u0131m i\xe7in l\xfctfen Ruffle wiki\'sine ba\u015fvurun.\nerror-wasm-cors =\n Ruffle gerekli ".wasm" dosya bile\u015fenini y\xfckleyemedi.\n Getirme eri\u015fimi muhtemelen CORS politikas\u0131 taraf\u0131ndan engellenmi\u015ftir.\n Sunucu y\xf6neticisiyseniz, yard\u0131m i\xe7in l\xfctfen Ruffle wiki\'sine ba\u015fvurun.\nerror-wasm-invalid =\n Ruffle, ba\u015flatmaya \xe7al\u0131\u015f\u0131rken \xf6nemli bir sorunla kar\u015f\u0131la\u015ft\u0131.\n G\xf6r\xfcn\xfc\u015fe g\xf6re bu sayfada Ruffle\'\u0131 \xe7al\u0131\u015ft\u0131rmak i\xe7in eksik veya ge\xe7ersiz dosyalar var.\n Sunucu y\xf6neticisiyseniz, yard\u0131m i\xe7in l\xfctfen Ruffle wiki\'sine ba\u015fvurun.\nerror-wasm-download =\n Ruffle, ba\u015flatmaya \xe7al\u0131\u015f\u0131rken \xf6nemli bir sorunla kar\u015f\u0131la\u015ft\u0131.\n Bu genellikle kendi kendine \xe7\xf6z\xfclebilir, bu nedenle sayfay\u0131 yeniden y\xfcklemeyi deneyebilirsiniz.\n Aksi takdirde, l\xfctfen site y\xf6neticisiyle ileti\u015fime ge\xe7in.\nerror-wasm-disabled-on-edge =\n Ruffle gerekli ".wasm" dosya bile\u015fenini y\xfckleyemedi.\n Bunu d\xfczeltmek i\xe7in taray\u0131c\u0131n\u0131z\u0131n ayarlar\u0131n\u0131 a\xe7\u0131n, "Gizlilik, arama ve hizmetler"i t\u0131klay\u0131n, a\u015fa\u011f\u0131 kayd\u0131r\u0131n ve "Web\'de g\xfcvenli\u011finizi art\u0131r\u0131n"\u0131 kapatmay\u0131 deneyin.\n Bu, taray\u0131c\u0131n\u0131z\u0131n gerekli ".wasm" dosyalar\u0131n\u0131 y\xfcklemesine izin verecektir.\n Sorun devam ederse, farkl\u0131 bir taray\u0131c\u0131 kullanman\u0131z gerekebilir.\nerror-javascript-conflict =\n Ruffle, ba\u015flatmaya \xe7al\u0131\u015f\u0131rken \xf6nemli bir sorunla kar\u015f\u0131la\u015ft\u0131.\n G\xf6r\xfcn\xfc\u015fe g\xf6re bu sayfa, Ruffle ile \xe7ak\u0131\u015fan JavaScript kodu kullan\u0131yor.\n Sunucu y\xf6neticisiyseniz, sizi dosyay\u0131 bo\u015f bir sayfaya y\xfcklemeyi denemeye davet ediyoruz.\nerror-javascript-conflict-outdated = Ayr\u0131ca sorunu giderebilecek daha yeni bir Ruffle s\xfcr\xfcm\xfc y\xfcklemeyi de deneyebilirsiniz (mevcut yap\u0131m eskimi\u015f: { $buildDate }).\nerror-csp-conflict =\n Ruffle, ba\u015flatmaya \xe7al\u0131\u015f\u0131rken \xf6nemli bir sorunla kar\u015f\u0131la\u015ft\u0131.\n Bu web sunucusunun \u0130\xe7erik G\xfcvenli\u011fi Politikas\u0131, gerekli ".wasm" bile\u015feninin \xe7al\u0131\u015fmas\u0131na izin vermiyor.\n Sunucu y\xf6neticisiyseniz, yard\u0131m i\xe7in l\xfctfen Ruffle wiki\'sine bak\u0131n.\nerror-unknown =\n Ruffle, bu Flash i\xe7eri\u011fini g\xf6r\xfcnt\xfclemeye \xe7al\u0131\u015f\u0131rken \xf6nemli bir sorunla kar\u015f\u0131la\u015ft\u0131.\n { $outdated ->\n [true] Sunucu y\xf6neticisiyseniz, l\xfctfen Ruffle\'\u0131n daha yeni bir s\xfcr\xfcm\xfcn\xfc y\xfcklemeyi deneyin (mevcut yap\u0131m eskimi\u015f: { $buildDate }).\n *[false] Bunun olmamas\u0131 gerekiyor, bu y\xfczden bir hata bildirebilirseniz \xe7ok memnun oluruz!\n }\n',"save-manager.ftl":"save-delete-prompt = Bu kay\u0131t dosyas\u0131n\u0131 silmek istedi\u011finize emin misiniz?\nsave-reload-prompt =\n Bu kaydetme dosyas\u0131n\u0131 potansiyel \xe7ak\u0131\u015fma olmadan { $action ->\n [delete] silmenin\n *[replace] de\u011fi\u015ftirmenin\n } tek yolu, bu i\xe7eri\u011fi yeniden y\xfcklemektir. Yine de devam etmek istiyor musunuz?\nsave-download = \u0130ndir\nsave-replace = De\u011fi\u015ftir\nsave-delete = Sil\nsave-backup-all = T\xfcm kay\u0131t dosyalar\u0131n\u0131 indir\n","volume-controls.ftl":"volume-controls = Ses kontrolleri\nvolume-controls-mute = Sustur\nvolume-controls-volume = Ses\n"},"zh-CN":{"context_menu.ftl":"context-menu-download-swf = \u4e0b\u8f7d .swf\ncontext-menu-copy-debug-info = \u590d\u5236\u8c03\u8bd5\u4fe1\u606f\ncontext-menu-open-save-manager = \u6253\u5f00\u5b58\u6863\u7ba1\u7406\u5668\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] \u5173\u4e8e Ruffle \u6269\u5c55 ({ $version })\n *[other] \u5173\u4e8e Ruffle ({ $version })\n }\ncontext-menu-hide = \u9690\u85cf\u6b64\u83dc\u5355\ncontext-menu-exit-fullscreen = \u9000\u51fa\u5168\u5c4f\ncontext-menu-enter-fullscreen = \u8fdb\u5165\u5168\u5c4f\ncontext-menu-volume-controls = \u97f3\u91cf\u63a7\u5236\n","messages.ftl":'message-cant-embed =\n Ruffle \u65e0\u6cd5\u8fd0\u884c\u5d4c\u5165\u5728\u6b64\u9875\u9762\u4e2d\u7684 Flash\u3002\n \u60a8\u53ef\u4ee5\u5c1d\u8bd5\u5728\u5355\u72ec\u7684\u6807\u7b7e\u9875\u4e2d\u6253\u5f00\u8be5\u6587\u4ef6\uff0c\u4ee5\u56de\u907f\u6b64\u95ee\u9898\u3002\npanic-title = \u51fa\u4e86\u4e9b\u95ee\u9898 :(\nmore-info = \u66f4\u591a\u4fe1\u606f\nrun-anyway = \u4ecd\u7136\u8fd0\u884c\ncontinue = \u7ee7\u7eed\nreport-bug = \u53cd\u9988\u95ee\u9898\nupdate-ruffle = \u66f4\u65b0 Ruffle\nruffle-demo = \u7f51\u9875\u6f14\u793a\nruffle-desktop = \u684c\u9762\u5e94\u7528\u7a0b\u5e8f\nruffle-wiki = \u67e5\u770b Ruffle Wiki\nenable-hardware-acceleration = \u770b\u8d77\u6765\u786c\u4ef6\u52a0\u901f\u672a\u542f\u7528\u3002\u867d\u7136 Ruffle \u53ef\u80fd\u8fd0\u884c\uff0c\u4f46\u53ef\u80fd\u4f1a\u975e\u5e38\u6162\u3002\u60a8\u53ef\u4ee5\u901a\u8fc7\u6b64\u94fe\u63a5\u4e86\u89e3\u542f\u7528\u786c\u4ef6\u52a0\u901f\u7684\u65b9\u6cd5\u3002\nview-error-details = \u67e5\u770b\u9519\u8bef\u8be6\u60c5\nopen-in-new-tab = \u5728\u65b0\u6807\u7b7e\u9875\u4e2d\u6253\u5f00\nclick-to-unmute = \u70b9\u51fb\u53d6\u6d88\u9759\u97f3\nerror-file-protocol =\n \u770b\u6765\u60a8\u6b63\u5728 "file:" \u534f\u8bae\u4e0a\u4f7f\u7528 Ruffle\u3002\n \u7531\u4e8e\u6d4f\u89c8\u5668\u4ee5\u5b89\u5168\u539f\u56e0\u963b\u6b62\u8bb8\u591a\u529f\u80fd\uff0c\u56e0\u6b64\u8fd9\u4e0d\u8d77\u4f5c\u7528\u3002\n \u76f8\u53cd\u6211\u4eec\u9080\u8bf7\u60a8\u8bbe\u7f6e\u672c\u5730\u670d\u52a1\u5668\u6216\u4f7f\u7528\u7f51\u9875\u6f14\u793a\u6216\u684c\u9762\u5e94\u7528\u7a0b\u5e8f\u3002\nerror-javascript-config =\n \u7531\u4e8e\u9519\u8bef\u7684 JavaScript \u914d\u7f6e\uff0cRuffle \u9047\u5230\u4e86\u4e00\u4e2a\u91cd\u5927\u95ee\u9898\u3002\n \u5982\u679c\u60a8\u662f\u670d\u52a1\u5668\u7ba1\u7406\u5458\uff0c\u6211\u4eec\u9080\u8bf7\u60a8\u68c0\u67e5\u9519\u8bef\u8be6\u7ec6\u4fe1\u606f\uff0c\u4ee5\u627e\u51fa\u54ea\u4e2a\u53c2\u6570\u6709\u6545\u969c\u3002\n \u60a8\u4e5f\u53ef\u4ee5\u67e5\u9605 Ruffle \u7684 Wiki \u83b7\u53d6\u5e2e\u52a9\u3002\nerror-wasm-not-found =\n Ruffle \u65e0\u6cd5\u52a0\u8f7d\u6240\u9700\u7684 \u201c.wasm\u201d \u6587\u4ef6\u7ec4\u4ef6\u3002\n \u5982\u679c\u60a8\u662f\u670d\u52a1\u5668\u7ba1\u7406\u5458\uff0c\u8bf7\u786e\u4fdd\u6587\u4ef6\u5df2\u6b63\u786e\u4e0a\u4f20\u3002\n \u5982\u679c\u95ee\u9898\u4ecd\u7136\u5b58\u5728\uff0c\u60a8\u53ef\u80fd\u9700\u8981\u4f7f\u7528 \u201cpublicPath\u201d \u8bbe\u7f6e\uff1a\u8bf7\u67e5\u770b Ruffle \u7684 Wiki \u83b7\u53d6\u5e2e\u52a9\u3002\nerror-wasm-mime-type =\n Ruffle \u5728\u8bd5\u56fe\u521d\u59cb\u5316\u65f6\u9047\u5230\u4e86\u4e00\u4e2a\u91cd\u5927\u95ee\u9898\u3002\n \u8be5\u7f51\u7ad9\u670d\u52a1\u5668\u6ca1\u6709\u63d0\u4f9b ".asm\u201d \u6587\u4ef6\u6b63\u786e\u7684 MIME \u7c7b\u578b\u3002\n \u5982\u679c\u60a8\u662f\u670d\u52a1\u5668\u7ba1\u7406\u5458\uff0c\u8bf7\u67e5\u9605 Ruffle Wiki \u83b7\u53d6\u5e2e\u52a9\u3002\nerror-swf-fetch =\n Ruffle \u65e0\u6cd5\u52a0\u8f7d Flash SWF \u6587\u4ef6\u3002\n \u6700\u53ef\u80fd\u7684\u539f\u56e0\u662f\u6587\u4ef6\u4e0d\u518d\u5b58\u5728\u6240\u4ee5 Ruffle \u6ca1\u6709\u8981\u52a0\u8f7d\u7684\u5185\u5bb9\u3002\n \u8bf7\u5c1d\u8bd5\u8054\u7cfb\u7f51\u7ad9\u7ba1\u7406\u5458\u5bfb\u6c42\u5e2e\u52a9\u3002\nerror-swf-cors =\n Ruffle \u65e0\u6cd5\u52a0\u8f7d Flash SWF \u6587\u4ef6\u3002\n \u83b7\u53d6\u6743\u9650\u53ef\u80fd\u88ab CORS \u7b56\u7565\u963b\u6b62\u3002\n \u5982\u679c\u60a8\u662f\u670d\u52a1\u5668\u7ba1\u7406\u5458\uff0c\u8bf7\u53c2\u8003 Ruffle Wiki \u83b7\u53d6\u5e2e\u52a9\u3002\nerror-wasm-cors =\n Ruffle \u65e0\u6cd5\u52a0\u8f7d\u6240\u9700\u7684\u201c.wasm\u201d\u6587\u4ef6\u7ec4\u4ef6\u3002\n \u83b7\u53d6\u6743\u9650\u53ef\u80fd\u88ab CORS \u7b56\u7565\u963b\u6b62\u3002\n \u5982\u679c\u60a8\u662f\u670d\u52a1\u5668\u7ba1\u7406\u5458\uff0c\u8bf7\u67e5\u9605 Ruffle Wiki \u83b7\u53d6\u5e2e\u52a9\u3002\nerror-wasm-invalid =\n Ruffle \u5728\u8bd5\u56fe\u521d\u59cb\u5316\u65f6\u9047\u5230\u4e86\u4e00\u4e2a\u91cd\u5927\u95ee\u9898\u3002\n \u8fd9\u4e2a\u9875\u9762\u4f3c\u4e4e\u7f3a\u5c11\u6587\u4ef6\u6765\u8fd0\u884c Curl\u3002\n \u5982\u679c\u60a8\u662f\u670d\u52a1\u5668\u7ba1\u7406\u5458\uff0c\u8bf7\u67e5\u9605 Ruffle Wiki \u83b7\u53d6\u5e2e\u52a9\u3002\nerror-wasm-download =\n Ruffle \u5728\u8bd5\u56fe\u521d\u59cb\u5316\u65f6\u9047\u5230\u4e86\u4e00\u4e2a\u91cd\u5927\u95ee\u9898\u3002\n \u8fd9\u901a\u5e38\u53ef\u4ee5\u81ea\u884c\u89e3\u51b3\uff0c\u56e0\u6b64\u60a8\u53ef\u4ee5\u5c1d\u8bd5\u91cd\u65b0\u52a0\u8f7d\u9875\u9762\u3002\n \u5426\u5219\u8bf7\u8054\u7cfb\u7f51\u7ad9\u7ba1\u7406\u5458\u3002\nerror-wasm-disabled-on-edge =\n Ruffle \u65e0\u6cd5\u52a0\u8f7d\u6240\u9700\u7684 \u201c.wasm\u201d \u6587\u4ef6\u7ec4\u4ef6\u3002\n \u8981\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0c\u8bf7\u5c1d\u8bd5\u6253\u5f00\u60a8\u7684\u6d4f\u89c8\u5668\u8bbe\u7f6e\uff0c\u5355\u51fb"\u9690\u79c1\u3001\u641c\u7d22\u548c\u670d\u52a1"\uff0c\u5411\u4e0b\u6eda\u52a8\u5e76\u5173\u95ed"\u589e\u5f3a Web \u5b89\u5168\u6027"\u3002\n \u8fd9\u5c06\u5141\u8bb8\u60a8\u7684\u6d4f\u89c8\u5668\u52a0\u8f7d\u6240\u9700\u7684 \u201c.wasm\u201d \u6587\u4ef6\u3002\n \u5982\u679c\u95ee\u9898\u4ecd\u7136\u5b58\u5728\uff0c\u60a8\u53ef\u80fd\u5fc5\u987b\u4f7f\u7528\u4e0d\u540c\u7684\u6d4f\u89c8\u5668\u3002\nerror-javascript-conflict =\n Ruffle \u5728\u8bd5\u56fe\u521d\u59cb\u5316\u65f6\u9047\u5230\u4e86\u4e00\u4e2a\u91cd\u5927\u95ee\u9898\u3002\n \u8fd9\u4e2a\u9875\u9762\u4f3c\u4e4e\u4f7f\u7528\u4e86\u4e0e Ruffle \u51b2\u7a81\u7684 JavaScript \u4ee3\u7801\u3002\n \u5982\u679c\u60a8\u662f\u670d\u52a1\u5668\u7ba1\u7406\u5458\uff0c\u6211\u4eec\u5efa\u8bae\u60a8\u5c1d\u8bd5\u5728\u7a7a\u767d\u9875\u9762\u4e0a\u52a0\u8f7d\u6587\u4ef6\u3002\nerror-javascript-conflict-outdated = \u60a8\u8fd8\u53ef\u4ee5\u5c1d\u8bd5\u4e0a\u4f20\u53ef\u80fd\u89c4\u907f\u8be5\u95ee\u9898\u7684\u6700\u65b0\u7248\u672c\u7684 (\u5f53\u524d\u6784\u5efa\u5df2\u8fc7\u65f6: { $buildDate })\u3002\nerror-csp-conflict =\n Ruffle \u5728\u8bd5\u56fe\u521d\u59cb\u5316\u65f6\u9047\u5230\u4e86\u4e00\u4e2a\u91cd\u5927\u95ee\u9898\u3002\n \u8be5\u7f51\u7ad9\u670d\u52a1\u5668\u7684\u5185\u5bb9\u5b89\u5168\u7b56\u7565\u4e0d\u5141\u8bb8\u8fd0\u884c\u6240\u9700\u7684 \u201c.wasm\u201d \u7ec4\u4ef6\u3002\n \u5982\u679c\u60a8\u662f\u670d\u52a1\u5668\u7ba1\u7406\u5458\uff0c\u8bf7\u67e5\u9605 Ruffle Wiki \u83b7\u53d6\u5e2e\u52a9\u3002\nerror-unknown =\n Ruffle \u5728\u8bd5\u56fe\u663e\u793a\u6b64 Flash \u5185\u5bb9\u65f6\u9047\u5230\u4e86\u4e00\u4e2a\u91cd\u5927\u95ee\u9898\u3002\n { $outdated ->\n [true] \u5982\u679c\u60a8\u662f\u670d\u52a1\u5668\u7ba1\u7406\u5458\uff0c\u8bf7\u5c1d\u8bd5\u4e0a\u4f20\u66f4\u65b0\u7684 Ruffle \u7248\u672c (\u5f53\u524d\u7248\u672c\u5df2\u8fc7\u65f6: { $buildDate }).\n *[false] \u8fd9\u4e0d\u5e94\u8be5\u53d1\u751f\uff0c\u56e0\u6b64\u5982\u679c\u60a8\u53ef\u4ee5\u62a5\u544a\u9519\u8bef\uff0c\u6211\u4eec\u5c06\u975e\u5e38\u611f\u8c22\uff01\n }\n',"save-manager.ftl":"save-delete-prompt = \u786e\u5b9a\u8981\u5220\u9664\u6b64\u5b58\u6863\u5417\uff1f\nsave-reload-prompt =\n \u4e3a\u4e86\u907f\u514d\u6f5c\u5728\u7684\u51b2\u7a81\uff0c{ $action ->\n [delete] \u5220\u9664\n *[replace] \u66ff\u6362\n } \u6b64\u5b58\u6863\u6587\u4ef6\u9700\u8981\u91cd\u65b0\u52a0\u8f7d\u5f53\u524d\u5185\u5bb9\u3002\u662f\u5426\u4ecd\u7136\u7ee7\u7eed\uff1f\nsave-download = \u4e0b\u8f7d\nsave-replace = \u66ff\u6362\nsave-delete = \u5220\u9664\nsave-backup-all = \u4e0b\u8f7d\u6240\u6709\u5b58\u6863\u6587\u4ef6\n","volume-controls.ftl":"volume-controls = \u97f3\u91cf\u63a7\u5236\nvolume-controls-mute = \u9759\u97f3\nvolume-controls-volume = \u97f3\u91cf\n"},"zh-TW":{"context_menu.ftl":"context-menu-download-swf = \u4e0b\u8f09SWF\u6a94\u6848\ncontext-menu-copy-debug-info = \u8907\u88fd\u9664\u932f\u8cc7\u8a0a\ncontext-menu-open-save-manager = \u6253\u958b\u5b58\u6a94\u7ba1\u7406\u5668\ncontext-menu-about-ruffle =\n { $flavor ->\n [extension] \u95dc\u65bcRuffle\u64f4\u5145\u529f\u80fd ({ $version })\n *[other] \u95dc\u65bcRuffle ({ $version })\n }\ncontext-menu-hide = \u96b1\u85cf\u83dc\u55ae\ncontext-menu-exit-fullscreen = \u9000\u51fa\u5168\u87a2\u5e55\ncontext-menu-enter-fullscreen = \u9032\u5165\u5168\u87a2\u5e55\ncontext-menu-volume-controls = \u97f3\u91cf\u63a7\u5236\n","messages.ftl":'message-cant-embed =\n \u76ee\u524dRuffle\u6c92\u8fa6\u6cd5\u57f7\u884c\u5d4c\u5165\u5f0fFlash\u3002\n \u4f60\u53ef\u4ee5\u5728\u65b0\u5206\u9801\u4e2d\u958b\u555f\u4f86\u89e3\u6c7a\u9019\u500b\u554f\u984c\u3002\npanic-title = \u5b8c\u86cb\uff0c\u51fa\u554f\u984c\u4e86 :(\nmore-info = \u66f4\u591a\u8cc7\u8a0a\nrun-anyway = \u76f4\u63a5\u57f7\u884c\ncontinue = \u7e7c\u7e8c\nreport-bug = \u56de\u5831BUG\nupdate-ruffle = \u66f4\u65b0Ruffle\nruffle-demo = \u7db2\u9801\u5c55\u793a\nruffle-desktop = \u684c\u9762\u61c9\u7528\u7a0b\u5f0f\nruffle-wiki = \u67e5\u770bRuffle Wiki\nenable-hardware-acceleration =\n \u770b\u8d77\u4f86\u4f60\u7684\u786c\u9ad4\u52a0\u901f\u6c92\u6709\u958b\u555f\uff0c\u96d6\u7136Ruffle\u9084\u53ef\u4ee5\u57f7\u884c\uff0c\u4f46\u662f\u4f60\u6703\u611f\u89ba\u5230\u6703\u5f88\u6162\u3002\n \u4f60\u53ef\u4ee5\u5728\u4e0b\u65b9\u9023\u7d50\u627e\u5230\u5982\u4f55\u958b\u555f\u786c\u9ad4\u52a0\u901f\u3002\nview-error-details = \u6aa2\u8996\u932f\u8aa4\u8a73\u7d30\u8cc7\u6599\nopen-in-new-tab = \u958b\u555f\u65b0\u589e\u5206\u9801\nclick-to-unmute = \u9ede\u64ca\u4ee5\u53d6\u6d88\u975c\u97f3\nerror-file-protocol =\n \u770b\u8d77\u4f86\u4f60\u60f3\u8981\u7528Ruffle\u4f86\u57f7\u884c"file:"\u7684\u5354\u8b70\u3002\n \u56e0\u70ba\u700f\u89bd\u5668\u7981\u4e86\u5f88\u591a\u529f\u80fd\u4ee5\u8cc7\u5b89\u7684\u7406\u7531\u4f86\u8b1b\u3002\n \u6211\u5011\u5efa\u8b70\u4f60\u5efa\u7acb\u672c\u5730\u4f3a\u670d\u5668\u6216\u8457\u76f4\u63a5\u4f7f\u7528\u7db2\u9801\u5c55\u793a\u6216\u684c\u9762\u61c9\u7528\u7a0b\u5f0f\u3002\nerror-javascript-config =\n \u76ee\u524dRuffle\u9047\u5230\u4e0d\u6b63\u78ba\u7684JavaScript\u914d\u7f6e\u3002\n \u5982\u679c\u4f60\u662f\u4f3a\u670d\u5668\u7ba1\u7406\u54e1\uff0c\u6211\u5011\u5efa\u8b70\u4f60\u6aa2\u67e5\u54ea\u500b\u74b0\u7bc0\u51fa\u932f\u3002\n \u6216\u8457\u4f60\u53ef\u4ee5\u67e5\u8a62Ruffle wiki\u5f97\u5230\u9700\u6c42\u5e6b\u52a9\u3002\nerror-wasm-not-found =\n \u76ee\u524dRuffle\u627e\u4e0d\u5230".wasm"\u6a94\u6848\u3002\n \u5982\u679c\u4f60\u662f\u4f3a\u670d\u5668\u7ba1\u7406\u54e1\uff0c\u78ba\u4fdd\u6a94\u6848\u662f\u5426\u653e\u5c0d\u4f4d\u7f6e\u3002\n \u5982\u679c\u9084\u662f\u6709\u554f\u984c\u7684\u8a71\uff0c\u4f60\u8981\u7528"publicPath"\u4f86\u8a2d\u5b9a: \u6216\u8457\u67e5\u8a62Ruffle wiki\u5f97\u5230\u9700\u6c42\u5e6b\u52a9\u3002\nerror-wasm-mime-type =\n \u76ee\u524dRuffle\u521d\u59cb\u5316\u6642\u9047\u5230\u91cd\u5927\u554f\u984c\u3002\n \u9019\u7db2\u9801\u4f3a\u670d\u5668\u4e26\u6c92\u6709\u670d\u52d9".wasm"\u6a94\u6848\u6216\u6b63\u78ba\u7684\u7db2\u969b\u7db2\u8def\u5a92\u9ad4\u985e\u578b\u3002\n \u5982\u679c\u4f60\u662f\u4f3a\u670d\u5668\u7ba1\u7406\u54e1\uff0c\u8acb\u67e5\u8a62Ruffle wiki\u5f97\u5230\u9700\u6c42\u5e6b\u52a9\u3002\nerror-swf-fetch =\n \u76ee\u524dRuffle\u7121\u6cd5\u8b80\u53d6Flash\u7684SWF\u6a94\u6848\u3002\n \u5f88\u6709\u53ef\u80fd\u8981\u8b80\u53d6\u7684\u6a94\u6848\u4e0d\u5b58\u5728\uff0c\u6240\u4ee5Ruffle\u8b80\u4e0d\u5230\u6771\u897f\u3002\n \u8acb\u5617\u8a66\u6e9d\u901a\u4f3a\u670d\u5668\u7ba1\u7406\u54e1\u5f97\u5230\u9700\u6c42\u5e6b\u52a9\u3002\nerror-swf-cors =\n \u76ee\u524dRuffle\u7121\u6cd5\u8b80\u53d6Flash\u7684SWF\u6a94\u6848\u3002\n \u770b\u8d77\u4f86\u662f\u4f7f\u7528\u6b0a\u88ab\u8de8\u4f86\u6e90\u8cc7\u6e90\u5171\u7528\u6a5f\u5236\u88ab\u64cb\u5230\u4e86\u3002\n \u5982\u679c\u4f60\u662f\u4f3a\u670d\u5668\u7ba1\u7406\u54e1\uff0c\u8acb\u67e5\u8a62Ruffle wiki\u5f97\u5230\u9700\u6c42\u5e6b\u52a9\u3002\nerror-wasm-cors =\n \u76ee\u524dRuffle\u7121\u6cd5\u8b80\u53d6".wasm"\u6a94\u6848\u3002\n \u770b\u8d77\u4f86\u662f\u4f7f\u7528\u6b0a\u88ab\u8de8\u4f86\u6e90\u8cc7\u6e90\u5171\u7528\u6a5f\u5236\u88ab\u64cb\u5230\u4e86\u3002\n \u5982\u679c\u4f60\u662f\u4f3a\u670d\u5668\u7ba1\u7406\u54e1\uff0c\u8acb\u67e5\u8a62Ruffle wiki\u5f97\u5230\u9700\u6c42\u5e6b\u52a9\u3002\nerror-wasm-invalid =\n \u76ee\u524dRuffle\u521d\u59cb\u5316\u6642\u9047\u5230\u91cd\u5927\u554f\u984c\u3002\n \u770b\u8d77\u4f86\u9019\u7db2\u9801\u6709\u7f3a\u5931\u6a94\u6848\u5c0e\u81f4Ruffle\u7121\u6cd5\u904b\u884c\u3002\n \u5982\u679c\u4f60\u662f\u4f3a\u670d\u5668\u7ba1\u7406\u54e1\uff0c\u8acb\u67e5\u8a62Ruffle wiki\u5f97\u5230\u9700\u6c42\u5e6b\u52a9\u3002\nerror-wasm-download =\n \u76ee\u524dRuffle\u521d\u59cb\u5316\u6642\u9047\u5230\u91cd\u5927\u554f\u984c\u3002\n \u9019\u53ef\u4ee5\u4f60\u81ea\u5df1\u89e3\u6c7a\uff0c\u4f60\u53ea\u8981\u91cd\u65b0\u6574\u7406\u5c31\u597d\u4e86\u3002\n \u5426\u5247\uff0c\u8acb\u5617\u8a66\u6e9d\u901a\u4f3a\u670d\u5668\u7ba1\u7406\u54e1\u5f97\u5230\u9700\u6c42\u5e6b\u52a9\u3002\nerror-wasm-disabled-on-edge =\n \u76ee\u524dRuffle\u7121\u6cd5\u8b80\u53d6".wasm"\u6a94\u6848\u3002\n \u8981\u4fee\u6b63\u7684\u8a71\uff0c\u6253\u958b\u4f60\u7684\u700f\u89bd\u5668\u8a2d\u5b9a\uff0c\u9ede\u9078"\u96b1\u79c1\u6b0a\u3001\u641c\u5c0b\u8207\u670d\u52d9"\uff0c\u628a"\u9632\u6b62\u8ffd\u8e64"\u7d66\u95dc\u6389\u3002\n \u9019\u6a23\u4e00\u4f86\u4f60\u7684\u700f\u89bd\u5668\u6703\u8b80\u53d6\u9700\u8981\u7684".wasm"\u6a94\u6848\u3002\n \u5982\u679c\u554f\u984c\u4e00\u76f4\u9084\u5728\u7684\u8a71\uff0c\u4f60\u5fc5\u9808\u8981\u63db\u700f\u89bd\u5668\u4e86\u3002\nerror-javascript-conflict =\n \u76ee\u524dRuffle\u521d\u59cb\u5316\u6642\u9047\u5230\u91cd\u5927\u554f\u984c\u3002\n \u770b\u8d77\u4f86\u9019\u7db2\u9801\u4f7f\u7528\u7684JavaScript\u6703\u8ddfRuffle\u8d77\u885d\u7a81\u3002\n \u5982\u679c\u4f60\u662f\u4f3a\u670d\u5668\u7ba1\u7406\u54e1\uff0c\u6211\u5011\u5efa\u8b70\u4f60\u958b\u500b\u7a7a\u767d\u9801\u4f86\u6e2c\u8a66\u3002\nerror-javascript-conflict-outdated = \u4f60\u4e5f\u53ef\u4ee5\u4e0a\u50b3\u6700\u65b0\u7248\u7684Ruffle\uff0c\u8aaa\u4e0d\u5b9a\u4f60\u8981\u8aaa\u7684\u7684\u554f\u984c\u5df2\u7d93\u4e0d\u898b\u4e86(\u73fe\u5728\u4f7f\u7528\u7684\u7248\u672c\u5df2\u7d93\u904e\u6642: { $buildDate })\u3002\nerror-csp-conflict =\n \u76ee\u524dRuffle\u521d\u59cb\u5316\u6642\u9047\u5230\u91cd\u5927\u554f\u984c\u3002\n \u9019\u7db2\u9801\u4f3a\u670d\u5668\u88ab\u8de8\u4f86\u6e90\u8cc7\u6e90\u5171\u7528\u6a5f\u5236\u7981\u6b62\u8b80\u53d6".wasm"\u6a94\u6848\u3002\n \u5982\u679c\u4f60\u662f\u4f3a\u670d\u5668\u7ba1\u7406\u54e1\uff0c\u8acb\u67e5\u8a62Ruffle wiki\u5f97\u5230\u9700\u6c42\u5e6b\u52a9\u3002\nerror-unknown =\n \u76ee\u524dRuffle\u521d\u59cb\u5316\u8981\u8b80\u53d6Flash\u5167\u5bb9\u6642\u9047\u5230\u91cd\u5927\u554f\u984c\n { $outdated ->\n [true] \u5982\u679c\u4f60\u662f\u4f3a\u670d\u5668\u7ba1\u7406\u54e1\uff0c \u8acb\u4e0a\u50b3\u6700\u65b0\u7248\u7684Ruffle(\u73fe\u5728\u4f7f\u7528\u7684\u7248\u672c\u5df2\u7d93\u904e\u6642: { $buildDate }).\n *[false] \u9019\u4e0d\u61c9\u8a72\u767c\u751f\u7684\uff0c\u6211\u5011\u4e5f\u5f88\u9ad8\u8208\u4f60\u544a\u77e5bug!\n }\n',"save-manager.ftl":"save-delete-prompt = \u4f60\u78ba\u5b9a\u8981\u522a\u9664\u9019\u500b\u5b58\u6a94\u55ce\uff1f\nsave-reload-prompt =\n \u552f\u4e00\u65b9\u6cd5\u53ea\u6709 { $action ->\n [delete] \u522a\u9664\n *[replace] \u53d6\u4ee3\n } \u9019\u500b\u5b58\u6a94\u4e0d\u6703\u5b8c\u5168\u53d6\u4ee3\u76f4\u5230\u91cd\u65b0\u555f\u52d5. \u4f60\u9700\u8981\u7e7c\u7e8c\u55ce?\nsave-download = \u4e0b\u8f09\nsave-replace = \u53d6\u4ee3\nsave-delete = \u522a\u9664\nsave-backup-all = \u4e0b\u8f09\u6240\u6709\u5b58\u6a94\u6a94\u6848\u3002\n","volume-controls.ftl":"volume-controls = \u97f3\u91cf\u63a7\u5236\nvolume-controls-mute = \u975c\u97f3\nvolume-controls-volume = \u97f3\u91cf\n"}},he={};for(const[e,n]of Object.entries(me)){const t=new P(e);if(n)for(const[r,a]of Object.entries(n))if(a)for(const n of t.addResource(new oe(a)))console.error(`Error in text for ${e} ${r}: ${n}`);he[e]=t}function pe(e,n,t){const r=he[e];if(void 0!==r){const e=r.getMessage(n);if(void 0!==e&&e.value)return r.formatPattern(e.value,t)}return null}function ve(e,n){const t=fe(navigator.languages,Object.keys(he),{defaultLocale:"en-US"});for(const r in t){const a=pe(t[r],e,n);if(a)return a}return console.error(`Unknown text key '${e}'`),e}function ge(e,n){const t=document.createElement("div");return ve(e,n).split("\n").forEach((e=>{const n=document.createElement("p");n.innerText=e,t.appendChild(n)})),t}function be(e,n,t,r,a){const i=a?document.createElementNS(a,e):document.createElement(e);if(n&&(i.id=n),t&&a?i.classList.add(t):t&&(i.className=t),r)for(const[e,n]of Object.entries(r))i.setAttribute(e,n);return i}function we(e,n,t,r,a){const i=be("input",n);return i.type=e,t&&(i.min=t),r&&(i.max=r),a&&(i.step=a),i}function ke(e,n){const t=be("label",e);return t.htmlFor=n,t}function ye(e,n){e.appendChild(n)}const xe=document.createElement("template"),Re="http://www.w3.org/2000/svg",_e=be("style","static-styles"),ze=be("style","dynamic-styles"),Se=be("div","container"),je=be("div","play-button"),Ee=be("div",void 0,"icon"),Ce=be("svg",void 0,void 0,{xmlns:Re,"xmlns:xlink":"http://www.w3.org/1999/xlink",preserveAspectRatio:"xMidYMid",viewBox:"0 0 250 250",width:"100%",height:"100%"},Re),Ae=be("defs",void 0,void 0,void 0,Re),Ie=be("linearGradient","a",void 0,{gradientUnits:"userSpaceOnUse",x1:"125",y1:"0",x2:"125",y2:"250",spreadMethod:"pad"},Re),Fe=be("stop",void 0,void 0,{offset:"0%","stop-color":"#FDA138"},Re),Oe=be("stop",void 0,void 0,{offset:"100%","stop-color":"#FD3A40"},Re),De=be("g","b",void 0,void 0,Re),Pe=be("path",void 0,void 0,{fill:"url(#a)",d:"M250 125q0-52-37-88-36-37-88-37T37 37Q0 73 0 125t37 88q36 37 88 37t88-37q37-36 37-88M87 195V55l100 70-100 70z"},Re),Te=be("path",void 0,void 0,{fill:"#FFF",d:"M87 55v140l100-70L87 55z"},Re),qe=document.createElementNS(Re,"use");qe.href.baseVal="#b";const Me=be("div","unmute-overlay"),Be=be("div",void 0,"background"),We=be("div",void 0,"icon"),Le=be("svg","unmute-overlay-svg",void 0,{xmlns:Re,"xmlns:xlink":"http://www.w3.org/1999/xlink",preserveAspectRatio:"xMidYMid",viewBox:"0 0 512 584",width:"100%",height:"100%",scale:"0.8"},Re),$e=be("path",void 0,void 0,{fill:"#FFF",stroke:"#FFF",d:"m457.941 256 47.029-47.029c9.372-9.373 9.372-24.568 0-33.941-9.373-9.373-24.568-9.373-33.941 0l-47.029 47.029-47.029-47.029c-9.373-9.373-24.568-9.373-33.941 0-9.372 9.373-9.372 24.568 0 33.941l47.029 47.029-47.029 47.029c-9.372 9.373-9.372 24.568 0 33.941 4.686 4.687 10.827 7.03 16.97 7.03s12.284-2.343 16.971-7.029l47.029-47.03 47.029 47.029c4.687 4.687 10.828 7.03 16.971 7.03s12.284-2.343 16.971-7.029c9.372-9.373 9.372-24.568 0-33.941z"},Re),Ne=be("path",void 0,void 0,{fill:"#FFF",stroke:"#FFF",d:"m99 160h-55c-24.301 0-44 19.699-44 44v104c0 24.301 19.699 44 44 44h55c2.761 0 5-2.239 5-5v-182c0-2.761-2.239-5-5-5z"},Re),Ue=be("path",void 0,void 0,{fill:"#FFF",stroke:"#FFF",d:"m280 56h-24c-5.269 0-10.392 1.734-14.578 4.935l-103.459 79.116c-1.237.946-1.963 2.414-1.963 3.972v223.955c0 1.557.726 3.026 1.963 3.972l103.459 79.115c4.186 3.201 9.309 4.936 14.579 4.936h23.999c13.255 0 24-10.745 24-24v-352.001c0-13.255-10.745-24-24-24z"},Re),Ze=be("text","unmute-text",void 0,{x:"256",y:"560","text-anchor":"middle","font-size":"60px",fill:"#FFF",stroke:"#FFF"},Re),He=be("input","virtual-keyboard",void 0,{type:"text",autocapitalize:"off",autocomplete:"off",autocorrect:"off"}),Je=be("div","splash-screen","hidden"),Ve=be("svg",void 0,"logo",{xmlns:Re,"xmlns:xlink":"http://www.w3.org/1999/xlink",preserveAspectRatio:"xMidYMid",viewBox:"0 0 380 150"},Re),Ke=be("g",void 0,void 0,void 0,Re),Ge=be("path",void 0,void 0,{fill:"#966214",d:"M58.75 85.6q.75-.1 1.5-.35.85-.25 1.65-.75.55-.35 1.05-.8.5-.45.95-1 .5-.5.75-1.2-.05.05-.15.1-.1.15-.25.25l-.1.2q-.15.05-.25.1-.4 0-.8.05-.5-.25-.9-.5-.3-.1-.55-.3l-.6-.6-4.25-6.45-1.5 11.25h3.45m83.15-.2h3.45q.75-.1 1.5-.35.25-.05.45-.15.35-.15.65-.3l.5-.3q.25-.15.5-.35.45-.35.9-.75.45-.35.75-.85l.1-.1q.1-.2.2-.35.2-.3.35-.6l-.3.4-.15.15q-.5.15-1.1.1-.25 0-.4-.05-.5-.15-.8-.4-.15-.1-.25-.25-.3-.3-.55-.6l-.05-.05v-.05l-4.25-6.4-1.5 11.25m-21.15-3.95q-.3-.3-.55-.6l-.05-.05v-.05l-4.25-6.4-1.5 11.25h3.45q.75-.1 1.5-.35.85-.25 1.6-.75.75-.5 1.4-1.1.45-.35.75-.85.35-.5.65-1.05l-.45.55q-.5.15-1.1.1-.9 0-1.45-.7m59.15.3q-.75-.5-1.4-1-3.15-2.55-3.5-6.4l-1.5 11.25h21q-3.1-.25-5.7-.75-5.6-1.05-8.9-3.1m94.2 3.85h3.45q.6-.1 1.2-.3.4-.1.75-.2.35-.15.65-.3.7-.35 1.35-.8.75-.55 1.3-1.25.1-.15.25-.3-2.55-.25-3.25-1.8l-4.2-6.3-1.5 11.25m-45.3-4.85q-.5-.4-.9-.8-2.3-2.35-2.6-5.6l-1.5 11.25h21q-11.25-.95-16-4.85m97.7 4.85q-.3-.05-.6-.05-10.8-1-15.4-4.8-3.15-2.55-3.5-6.35l-1.5 11.2h21Z"},Re),Ye=be("path",void 0,void 0,{fill:"var(--ruffle-orange)",d:"M92.6 54.8q-1.95-1.4-4.5-1.4H60.35q-1.35 0-2.6.45-1.65.55-3.15 1.8-2.75 2.25-3.25 5.25l-1.65 12h.05v.3l5.85 1.15h-9.5q-.5.05-1 .15-.5.15-1 .35-.5.2-.95.45-.5.3-.95.7-.45.35-.85.8-.35.4-.65.85-.3.45-.5.9-.15.45-.3.95l-5.85 41.6H50.3l5-35.5 1.5-11.25 4.25 6.45.6.6q.25.2.55.3.4.25.9.5.4-.05.8-.05.1-.05.25-.1l.1-.2q.15-.1.25-.25.1-.05.15-.1l.3-1.05 1.75-12.3h11.15L75.8 82.6h16.5l2.3-16.25h-.05l.8-5.7q.4-2.45-1-4.2-.35-.4-.75-.8-.25-.25-.55-.5-.2-.2-.45-.35m16.2 18.1h.05l-.05.3 5.85 1.15H105.2q-.5.05-1 .15-.5.15-1 .35-.5.2-.95.45-.5.3-1 .65-.4.4-.8.85-.25.3-.55.65-.05.1-.15.2-.25.45-.4.9-.2.45-.3.95-.1.65-.2 1.25-.2 1.15-.4 2.25l-4.3 30.6q-.25 3 1.75 5.25 1.6 1.8 4 2.15.6.1 1.25.1h27.35q3.25 0 6-2.25.35-.35.7-.55l.3-.2q2-2 2.25-4.5l1.65-11.6q.05-.05.1-.05l1.65-11.35h.05l.7-5.2 1.5-11.25 4.25 6.4v.05l.05.05q.25.3.55.6.1.15.25.25.3.25.8.4.15.05.4.05.6.05 1.1-.1l.15-.15.3-.4.3-1.05 1.3-9.05h-.05l.7-5.05h-.05l.15-1.25h-.05l1.65-11.7h-16.25l-2.65 19.5h.05v.2l-.05.1h.05l5.8 1.15H132.7q-.5.05-1 .15-.5.15-1 .35-.15.05-.3.15-.3.1-.55.25-.05 0-.1.05-.5.3-1 .65-.4.35-.7.7-.55.7-.95 1.45-.35.65-.55 1.4-.15.7-.25 1.4v.05q-.15 1.05-.35 2.05l-1.2 8.75v.1l-2.1 14.7H111.4l2.25-15.55h.05l.7-5.2 1.5-11.25 4.25 6.4v.05l.05.05q.25.3.55.6.55.7 1.45.7.6.05 1.1-.1l.45-.55.3-1.05 1.3-9.05h-.05l.7-5.05h-.05l.15-1.25h-.05l1.65-11.7h-16.25l-2.65 19.5m106.5-41.75q-2.25-2.25-5.5-2.25h-27.75q-3 0-5.75 2.25-1.3.95-2.05 2.1-.45.6-.7 1.2-.2.5-.35 1-.1.45-.15.95l-4.15 29.95h-.05l-.7 5.2h-.05l-.2 1.35h.05l-.05.3 5.85 1.15h-9.45q-2.1.05-3.95 1.6-1.9 1.55-2.25 3.55l-.5 3.5h-.05l-5.3 38.1h16.25l5-35.5 1.5-11.25q.35 3.85 3.5 6.4.65.5 1.4 1 3.3 2.05 8.9 3.1 2.6.5 5.7.75l1.75-11.25h-12.2l.4-2.95h-.05l.7-5.05h-.05q.1-.9.3-1.9.1-.75.2-1.6.85-5.9 2.15-14.9 0-.15.05-.25l.1-.9q.2-1.55.45-3.15h11.25l-3.1 20.8h16.5l4.1-28.05q.15-1.7-.4-3.15-.5-1.1-1.35-2.1m46.65 44.15q-.5.3-1 .65-.4.4-.8.85-.35.4-.7.85-.25.45-.45.9-.15.45-.3.95l-5.85 41.6h16.25l5-35.5 1.5-11.25 4.2 6.3q.7 1.55 3.25 1.8l.05-.1q.25-.4.35-.85l.3-1.05 1.8-14.05v-.05l5.35-37.45h-16.25l-6.15 44.3 5.85 1.15h-9.45q-.5.05-1 .15-.5.15-1 .35-.5.2-.95.45m5.4-38.9q.15-1.7-.4-3.15-.5-1.1-1.35-2.1-2.25-2.25-5.5-2.25h-27.75q-2.3 0-4.45 1.35-.65.35-1.3.9-1.3.95-2.05 2.1-.45.6-.7 1.2-.4.9-.5 1.95l-4.15 29.95h-.05l-.7 5.2h-.05l-.2 1.35h.05l-.05.3 5.85 1.15h-9.45q-2.1.05-3.95 1.6-1.9 1.55-2.25 3.55l-.5 3.5h-.05l-1.2 8.75v.1l-4.1 29.25h16.25l5-35.5 1.5-11.25q.3 3.25 2.6 5.6.4.4.9.8 4.75 3.9 16 4.85l1.75-11.25h-12.2l.4-2.95h-.05l.7-5.05h-.05q.15-.9.3-1.9.1-.75.25-1.6.15-1.25.35-2.65v-.05q.95-6.7 2.35-16.5h11.25l-3.1 20.8h16.5l4.1-28.05M345 66.35h-.05l1.15-8.2q.5-3-1.75-5.25-1.25-1.25-3-1.75-1-.5-2.25-.5h-27.95q-.65 0-1.3.1-2.5.35-4.7 2.15-2.75 2.25-3.25 5.25l-1.95 14.7v.05l-.05.3 5.85 1.15h-9.45q-1.9.05-3.6 1.35-.2.1-.35.25-1.9 1.55-2.25 3.55l-4.85 34.1q-.25 3 1.75 5.25 1.25 1.4 3 1.95 1.05.3 2.25.3H320q3.25 0 6-2.25 2.75-2 3.25-5l2.75-18.5h-16.5l-1.75 11H302.5l2.1-14.75h.05l.85-6 1.5-11.2q.35 3.8 3.5 6.35 4.6 3.8 15.4 4.8.3 0 .6.05h15.75L345 66.35m-16.4-.95-1.25 8.95h-11.3l.4-2.95h-.05l.7-5.05h-.1l.15-.95h11.45Z"},Re),Xe=be("svg",void 0,"loading-animation",{xmlns:Re,viewBox:"0 0 66 66"},Re),Qe=be("circle",void 0,"spinner",{fill:"none","stroke-width":"6","stroke-linecap":"round",cx:"33",cy:"33",r:"30"},Re),en=be("div",void 0,"loadbar"),nn=be("div",void 0,"loadbar-inner"),tn=be("div","save-manager","modal hidden"),rn=be("div","modal-area","modal-area"),an=be("span",void 0,"close-modal");an.textContent="\xd7";const on=be("div",void 0,"general-save-options"),sn=be("span","backup-saves","save-option"),ln=be("table","local-saves"),un=be("div","volume-controls-modal","modal hidden"),cn=be("div",void 0,"modal-area"),dn=be("span",void 0,"close-modal");dn.textContent="\xd7";const fn=be("div","volume-controls"),mn=be("h2","volume-controls-heading"),hn=ke("mute-checkbox-label","mute-checkbox"),pn=we("checkbox","mute-checkbox"),vn=be("div",void 0,"slider-container"),gn=ke("volume-slider-label","volume-slider"),bn=we("range","volume-slider","0","100","1"),wn=be("span","volume-slider-text"),kn=be("div","video-modal","modal hidden"),yn=be("div",void 0,"modal-area"),xn=be("span",void 0,"close-modal");xn.textContent="\xd7";const Rn=be("div","video-holder"),_n=be("div","hardware-acceleration-modal","modal hidden"),zn=be("div",void 0,"modal-area"),Sn=be("span",void 0,"close-modal");Sn.textContent="\xd7";const jn=document.createElement("a");jn.href="https://github.com/ruffle-rs/ruffle/wiki/Frequently-Asked-Questions-For-Users#chrome-hardware-acceleration",jn.target="_blank",jn.className="acceleration-link",jn.textContent=ve("enable-hardware-acceleration");const En=be("div","context-menu-overlay","hidden"),Cn=be("ul","context-menu");ye(xe.content,_e),ye(xe.content,ze),ye(xe.content,Se),ye(Se,je),ye(je,Ee),ye(Ee,Ce),ye(Ce,Ae),ye(Ae,Ie),ye(Ie,Fe),ye(Ie,Oe),ye(Ae,De),ye(De,Pe),ye(De,Te),ye(Ce,qe),ye(Se,Me),ye(Me,Be),ye(Me,We),ye(We,Le),ye(Le,$e),ye(Le,Ne),ye(Le,Ue),ye(Le,Ze),ye(Se,He),ye(xe.content,Je),ye(Je,Ve),ye(Ve,Ke),ye(Ke,Ge),ye(Ke,Ye),ye(Je,Xe),ye(Xe,Qe),ye(Je,en),ye(en,nn),ye(xe.content,tn),ye(tn,rn),ye(rn,an),ye(rn,on),ye(on,sn),ye(rn,ln),ye(xe.content,un),ye(un,cn),ye(cn,dn),ye(cn,fn),ye(fn,mn),ye(fn,hn),ye(fn,pn),ye(fn,vn),ye(vn,gn),ye(vn,bn),ye(vn,wn),ye(xe.content,kn),ye(kn,yn),ye(yn,xn),ye(yn,Rn),ye(xe.content,_n),ye(_n,zn),ye(zn,Sn),ye(zn,jn),ye(xe.content,En),ye(En,Cn);const An={};function In(e,n){const t=An[e];if(void 0!==t){if(t.class!==n)throw new Error("Internal naming conflict on "+e);return t.name}let r=0;if(void 0!==window.customElements)for(;r<999;){let t=e;if(r>0&&(t=t+"-"+r),void 0===window.customElements.get(t))return window.customElements.define(t,n),An[e]={class:n,name:t,internalName:e},t;r+=1}throw new Error("Failed to assign custom element "+e)}var Fn,On,Dn,Pn,Tn,qn,Mn,Bn,Wn,Ln;!function(e){e.On="on",e.Off="off",e.Auto="auto"}(Fn||(Fn={})),function(e){e.Off="off",e.Fullscreen="fullscreen",e.On="on"}(On||(On={})),function(e){e.Visible="visible",e.Hidden="hidden"}(Dn||(Dn={})),function(e){e.Error="error",e.Warn="warn",e.Info="info",e.Debug="debug",e.Trace="trace"}(Pn||(Pn={})),function(e){e.Window="window",e.Opaque="opaque",e.Transparent="transparent",e.Direct="direct",e.Gpu="gpu"}(Tn||(Tn={})),function(e){e.WebGpu="webgpu",e.WgpuWebgl="wgpu-webgl",e.Webgl="webgl",e.Canvas="canvas"}(qn||(qn={})),function(e){e.On="on",e.RightClickOnly="rightClickOnly",e.Off="off"}(Mn||(Mn={})),function(e){e.AIR="air",e.FlashPlayer="flashPlayer"}(Bn||(Bn={})),function(e){e.Allow="allow",e.Confirm="confirm",e.Deny="deny"}(Wn||(Wn={})),function(e){e.All="all",e.Internal="internal",e.None="none"}(Ln||(Ln={}));const $n={allowScriptAccess:!1,parameters:{},autoplay:Fn.Auto,backgroundColor:null,letterbox:On.Fullscreen,unmuteOverlay:Dn.Visible,upgradeToHttps:!0,compatibilityRules:!0,favorFlash:!0,warnOnUnsupportedContent:!0,logLevel:Pn.Error,showSwfDownload:!1,contextMenu:Mn.On,preloader:!0,splashScreen:!0,maxExecutionDuration:15,base:null,menu:!0,salign:"",forceAlign:!1,quality:"high",scale:"showAll",forceScale:!1,frameRate:null,wmode:Tn.Window,publicPath:null,polyfills:!0,playerVersion:null,preferredRenderer:null,openUrlMode:Wn.Allow,allowNetworking:Ln.All,openInNewTab:null,socketProxy:[],fontSources:[],defaultFonts:{},credentialAllowList:[],playerRuntime:Bn.FlashPlayer},Nn="application/x-shockwave-flash",Un="application/futuresplash",Zn="application/x-shockwave-flash2-preview",Hn="application/vnd.adobe.flash.movie";function Jn(e,n){const t=function(e){let n="";try{n=new URL(e,"https://example.com").pathname}catch(e){}if(n&&n.length>=4){const e=n.slice(-4).toLowerCase();if(".swf"===e||".spl"===e)return!0}return!1}(e);return n?function(e,n){switch(e=e.toLowerCase()){case Nn.toLowerCase():case Un.toLowerCase():case Zn.toLowerCase():case Hn.toLowerCase():return!0;default:if(n)switch(e){case"application/octet-stream":case"binary/octet-stream":return!0}}return!1}(n,t):t}const Vn={versionNumber:"0.1.0",versionName:"nightly 2024-01-08",versionChannel:"nightly",buildDate:"2024-01-08T00:15:28.895Z",commitHash:"47db84473a639c405289bb86ce238a83af574137"};var Kn=a(297),Gn=a.n(Kn);const Yn="https://ruffle.rs",Xn=/^\s*(\d+(\.\d+)?(%)?)/;let Qn=!1;var et,nt;function tt(e){if(null==e)return{};e instanceof URLSearchParams||(e=new URLSearchParams(e));const n={};for(const[t,r]of e)n[t]=r.toString();return n}!function(e){e[e.Unknown=0]="Unknown",e[e.CSPConflict=1]="CSPConflict",e[e.FileProtocol=2]="FileProtocol",e[e.InvalidWasm=3]="InvalidWasm",e[e.JavascriptConfiguration=4]="JavascriptConfiguration",e[e.JavascriptConflict=5]="JavascriptConflict",e[e.WasmCors=6]="WasmCors",e[e.WasmDownload=7]="WasmDownload",e[e.WasmMimeType=8]="WasmMimeType",e[e.WasmNotFound=9]="WasmNotFound",e[e.WasmDisabledMicrosoftEdge=10]="WasmDisabledMicrosoftEdge",e[e.SwfFetchError=11]="SwfFetchError",e[e.SwfCors=12]="SwfCors"}(et||(et={}));class rt{constructor(e,n){this.x=e,this.y=n}distanceTo(e){const n=e.x-this.x,t=e.y-this.y;return Math.sqrt(n*n+t*t)}}class at{constructor(e="#",n=ve("view-error-details")){this.url=e,this.label=n}}class it extends HTMLElement{get readyState(){return this._readyState}get metadata(){return this._metadata}constructor(){super(),this.contextMenuForceDisabled=!1,this.isTouch=!1,this.contextMenuSupported=!1,this.panicked=!1,this.rendererDebugInfo="",this.longPressTimer=null,this.pointerDownPosition=null,this.pointerMoveMaxDistance=0,this.config={},this.shadow=this.attachShadow({mode:"open"}),this.shadow.appendChild(xe.content.cloneNode(!0)),this.dynamicStyles=this.shadow.getElementById("dynamic-styles"),this.staticStyles=this.shadow.getElementById("static-styles"),this.container=this.shadow.getElementById("container"),this.playButton=this.shadow.getElementById("play-button"),this.playButton.addEventListener("click",(()=>this.play())),this.unmuteOverlay=this.shadow.getElementById("unmute-overlay"),this.splashScreen=this.shadow.getElementById("splash-screen"),this.virtualKeyboard=this.shadow.getElementById("virtual-keyboard"),this.virtualKeyboard.addEventListener("input",this.virtualKeyboardInput.bind(this)),this.saveManager=this.shadow.getElementById("save-manager"),this.videoModal=this.shadow.getElementById("video-modal"),this.hardwareAccelerationModal=this.shadow.getElementById("hardware-acceleration-modal"),this.volumeControls=this.shadow.getElementById("volume-controls-modal"),this.addModalJavaScript(this.saveManager),this.addModalJavaScript(this.volumeControls),this.addModalJavaScript(this.videoModal),this.addModalJavaScript(this.hardwareAccelerationModal),this.volumeSettings=new dt(!1,100),this.addVolumeControlsJavaScript(this.volumeControls);const e=this.saveManager.querySelector("#backup-saves");e&&(e.addEventListener("click",this.backupSaves.bind(this)),e.innerText=ve("save-backup-all"));const n=this.unmuteOverlay.querySelector("#unmute-overlay-svg");if(n){n.querySelector("#unmute-text").textContent=ve("click-to-unmute")}this.contextMenuOverlay=this.shadow.getElementById("context-menu-overlay"),this.contextMenuElement=this.shadow.getElementById("context-menu"),document.documentElement.addEventListener("pointerdown",this.checkIfTouch.bind(this)),this.addEventListener("contextmenu",this.showContextMenu.bind(this)),this.container.addEventListener("pointerdown",this.pointerDown.bind(this)),this.container.addEventListener("pointermove",this.checkLongPressMovement.bind(this)),this.container.addEventListener("pointerup",this.checkLongPress.bind(this)),this.container.addEventListener("pointercancel",this.clearLongPressTimer.bind(this)),this.addEventListener("fullscreenchange",this.fullScreenChange.bind(this)),this.addEventListener("webkitfullscreenchange",this.fullScreenChange.bind(this)),this.instance=null,this.onFSCommand=null,this._readyState=nt.HaveNothing,this._metadata=null,this.lastActivePlayingState=!1,this.setupPauseOnTabHidden()}addModalJavaScript(e){const n=e.querySelector("#video-holder");this.container.addEventListener("click",(()=>{e.classList.add("hidden"),n&&(n.textContent="")}));const t=e.querySelector(".modal-area");t&&t.addEventListener("click",(e=>e.stopPropagation()));const r=e.querySelector(".close-modal");r&&r.addEventListener("click",(()=>{e.classList.add("hidden"),n&&(n.textContent="")}))}addVolumeControlsJavaScript(e){const n=e.querySelector("#mute-checkbox"),t=e.querySelector("#volume-slider"),r=e.querySelector("#volume-slider-text"),a=e.querySelector("#volume-controls-heading"),i=e.querySelector("#mute-checkbox-label"),o=e.querySelector("#volume-slider-label");a.textContent=ve("volume-controls"),i.textContent=ve("volume-controls-mute"),o.textContent=ve("volume-controls-volume"),n.checked=this.volumeSettings.isMuted,t.disabled=n.checked,t.valueAsNumber=this.volumeSettings.volume,o.style.color=n.checked?"grey":"black",r.style.color=n.checked?"grey":"black",r.textContent=String(this.volumeSettings.volume),n.addEventListener("change",(()=>{var e;t.disabled=n.checked,o.style.color=n.checked?"grey":"black",r.style.color=n.checked?"grey":"black",this.volumeSettings.isMuted=n.checked,null===(e=this.instance)||void 0===e||e.set_volume(this.volumeSettings.get_volume())})),t.addEventListener("input",(()=>{var e;r.textContent=t.value,this.volumeSettings.volume=t.valueAsNumber,null===(e=this.instance)||void 0===e||e.set_volume(this.volumeSettings.get_volume())}))}setupPauseOnTabHidden(){document.addEventListener("visibilitychange",(()=>{this.instance&&(document.hidden&&(this.lastActivePlayingState=this.instance.is_playing(),this.instance.pause()),document.hidden||!0!==this.lastActivePlayingState||this.instance.play())}),!1)}get height(){return this.getAttribute("height")||""}set height(e){this.setAttribute("height",e)}get width(){return this.getAttribute("width")||""}set width(e){this.setAttribute("width",e)}get type(){return this.getAttribute("type")||""}set type(e){this.setAttribute("type",e)}connectedCallback(){this.updateStyles(),function(e){if(!e.sheet)return;const n=[":host {\n all: initial;\n pointer-events: inherit;\n\n --ruffle-blue: #37528c;\n --ruffle-orange: #ffad33;\n\n display: inline-block;\n position: relative;\n /* Default width/height; this will get overridden by user styles/attributes. */\n width: 550px;\n height: 400px;\n font-family: Arial, sans-serif;\n letter-spacing: 0.4px;\n touch-action: none;\n user-select: none;\n -webkit-user-select: none;\n -webkit-tap-highlight-color: transparent;\n }",":host(:-webkit-full-screen) {\n display: block;\n width: 100% !important;\n height: 100% !important;\n }",".hidden {\n display: none !important;\n }","#container,\n #play-button,\n #unmute-overlay,\n #unmute-overlay .background,\n #panic,\n #splash-screen,\n #message-overlay {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n }","#container {\n overflow: hidden;\n }","#container canvas {\n width: 100%;\n height: 100%;\n }","#play-button,\n #unmute-overlay {\n cursor: pointer;\n display: none;\n }","#unmute-overlay .background {\n background: black;\n opacity: 0.7;\n }","#play-button .icon,\n #unmute-overlay .icon {\n position: absolute;\n top: 50%;\n left: 50%;\n width: 50%;\n height: 50%;\n max-width: 384px;\n max-height: 384px;\n transform: translate(-50%, -50%);\n opacity: 0.8;\n }","#play-button:hover .icon,\n #unmute-overlay:hover .icon {\n opacity: 1;\n }","#panic {\n font-size: 20px;\n text-align: center;\n background: linear-gradient(180deg, #fd3a40 0%, #fda138 100%);\n color: white;\n display: flex;\n flex-flow: column;\n justify-content: space-around;\n }","#panic a {\n color: var(--ruffle-blue);\n font-weight: bold;\n }","#panic-title {\n font-size: xxx-large;\n font-weight: bold;\n }","#panic-body.details {\n flex: 0.9;\n margin: 0 10px;\n }","#panic-body textarea {\n width: 100%;\n height: 100%;\n resize: none;\n }","#panic ul {\n padding: 0;\n display: flex;\n list-style-type: none;\n justify-content: space-evenly;\n }","#message-overlay {\n position: absolute;\n background: var(--ruffle-blue);\n color: var(--ruffle-orange);\n opacity: 1;\n z-index: 2;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: auto;\n }","#message-overlay .message {\n text-align: center;\n max-height: 100%;\n max-width: 100%;\n padding: 5%;\n font-size: 20px;\n }","#message-overlay p {\n margin: 0.5em 0;\n }","#message-overlay .message div {\n display: flex;\n justify-content: center;\n flex-wrap: wrap;\n column-gap: 1em;\n }","#message-overlay a, #message-overlay button {\n cursor: pointer;\n background: var(--ruffle-blue);\n color: var(--ruffle-orange);\n border: 2px solid var(--ruffle-orange);\n font-weight: bold;\n font-size: 1.25em;\n border-radius: 0.6em;\n padding: 10px;\n text-decoration: none;\n margin: 2% 0;\n }","#message-overlay a:hover, #message-overlay button:hover {\n background: #ffffff4c;\n }","#continue-btn {\n cursor: pointer;\n background: var(--ruffle-blue);\n color: var(--ruffle-orange);\n border: 2px solid var(--ruffle-orange);\n font-weight: bold;\n font-size: 20px;\n border-radius: 20px;\n padding: 10px;\n }","#continue-btn:hover {\n background: #ffffff4c;\n }","#context-menu-overlay {\n width: 100%;\n height: 100%;\n z-index: 1;\n position: absolute;\n }","#context-menu {\n color: black;\n background: #fafafa;\n border: 1px solid gray;\n box-shadow: 0px 5px 10px -5px black;\n position: absolute;\n font-size: 14px;\n text-align: left;\n list-style: none;\n padding: 0;\n margin: 0;\n }","#context-menu .menu-item {\n padding: 5px 10px;\n cursor: pointer;\n color: black;\n }","#context-menu .menu-item.disabled {\n cursor: default;\n color: gray;\n }","#context-menu .menu-item:not(.disabled):hover {\n background: lightgray;\n }","#context-menu .menu-separator hr {\n border: none;\n border-bottom: 1px solid lightgray;\n margin: 2px;\n }","#splash-screen {\n display: flex;\n flex-direction: column;\n background: var(--splash-screen-background, var(--preloader-background, var(--ruffle-blue)));\n align-items: center;\n justify-content: center;\n }",".loadbar {\n width: 100%;\n max-width: 316px;\n max-height: 10px;\n height: 20%;\n background: #253559;\n }",".loadbar-inner {\n width: 0px;\n max-width: 100%;\n height: 100%;\n background: var(--ruffle-orange);\n }",".logo {\n display: var(--logo-display, block);\n max-width: 380px;\n max-height: 150px;\n }",".loading-animation {\n max-width: 28px;\n max-height: 28px;\n margin-bottom: 2%;\n width: 10%;\n aspect-ratio: 1;\n }",".spinner {\n stroke-dasharray: 180;\n stroke-dashoffset: 135;\n stroke: var(--ruffle-orange);\n transform-origin: 50% 50%;\n animation: rotate 1.5s linear infinite;\n }","@keyframes rotate {\n to {\n transform: rotate(360deg);\n }\n }","#virtual-keyboard {\n position: absolute;\n opacity: 0;\n top: -100px;\n width: 1px;\n height: 1px;\n }",".modal {\n height: inherit;\n user-select: text;\n }",".modal-area {\n position: sticky;\n background: white;\n width: fit-content;\n padding: 16px 28px 16px 16px;\n border: 3px solid black;\n margin: auto;\n }","#modal-area {\n height: 500px;\n max-height: calc(100% - 38px);\n min-height: 80px;\n }","#restore-save {\n display: none;\n }",".replace-save {\n display: none;\n }",".save-option {\n display: inline-block;\n padding: 3px 10px;\n margin: 5px 2px;\n cursor: pointer;\n border-radius: 50px;\n background-color: var(--ruffle-blue);\n color: white;\n }",".close-modal {\n position: absolute;\n top: 5px;\n right: 10px;\n cursor: pointer;\n font-size: x-large;\n }",".general-save-options {\n text-align: center;\n padding-bottom: 8px;\n border-bottom: 2px solid #888;\n }","#local-saves {\n border-collapse: collapse;\n overflow-y: auto;\n display: block;\n padding-right: 16px;\n height: calc(100% - 45px);\n min-height: 30px;\n }","#local-saves td {\n border-bottom: 1px solid #bbb;\n height: 30px;\n }","#local-saves tr td:nth-child(1) {\n padding-right: 1em;\n word-break: break-all;\n }","#local-saves tr:nth-child(even) {\n background-color: #f2f2f2;\n }","#video-holder {\n padding-top: 20px;\n }","#video-holder video {\n max-width: 100%;\n height: calc(100% - 58px);\n }",".slider-container {\n margin-top: 10px;\n display: flex;\n align-items: center;\n }","#volume-slider {\n margin-left: 10px;\n margin-right: 10px;\n }","#volume-slider-text {\n text-align: right;\n width: 28px;\n }",".acceleration-link {\n color: var(--ruffle-blue);\n text-decoration: none;\n }",".acceleration-link:hover {\n text-decoration: underline;\n }"];!function(e,n){for(const t of n)try{e.insertRule(t)}catch(e){}}(e.sheet,n)}(this.staticStyles)}static get observedAttributes(){return["width","height"]}attributeChangedCallback(e,n,t){"width"!==e&&"height"!==e||this.updateStyles()}disconnectedCallback(){this.destroy()}updateStyles(){if(this.dynamicStyles.sheet){if(this.dynamicStyles.sheet.cssRules)for(let e=this.dynamicStyles.sheet.cssRules.length-1;e>=0;e--)this.dynamicStyles.sheet.deleteRule(e);const e=this.attributes.getNamedItem("width");if(null!=e){const n=it.htmlDimensionToCssDimension(e.value);null!==n&&this.dynamicStyles.sheet.insertRule(`:host { width: ${n}; }`)}const n=this.attributes.getNamedItem("height");if(null!=n){const e=it.htmlDimensionToCssDimension(n.value);null!==e&&this.dynamicStyles.sheet.insertRule(`:host { height: ${e}; }`)}}}isUnusedFallbackObject(){const e=function(e){const n=An[e];return void 0!==n?{internalName:e,name:n.name,class:n.class}:null}("ruffle-object");if(null!==e){let n=this.parentNode;for(;n!==document&&null!==n;){if(n.nodeName===e.name)return!0;n=n.parentNode}}return!1}async ensureFreshInstance(){var e,n,t,r,a,i,o,s,l,u,c;if(this.destroy(),this.loadedConfig&&!1!==this.loadedConfig.splashScreen&&!1!==this.loadedConfig.preloader&&this.showSplashScreen(),this.loadedConfig&&!1===this.loadedConfig.preloader&&console.warn("The configuration option preloader has been replaced with splashScreen. If you own this website, please update the configuration."),this.loadedConfig&&this.loadedConfig.maxExecutionDuration&&"number"!=typeof this.loadedConfig.maxExecutionDuration&&console.warn("Configuration: An obsolete format for duration for 'maxExecutionDuration' was used, please use a single number indicating seconds instead. For instance '15' instead of '{secs: 15, nanos: 0}'."),this.loadedConfig&&"boolean"==typeof this.loadedConfig.contextMenu&&console.warn('The configuration option contextMenu no longer takes a boolean. Use "on", "off", or "rightClickOnly".'),this.instance=await h(this.container,this,this.loadedConfig||{},this.onRuffleDownloadProgress.bind(this)).catch((e=>{if(console.error(`Serious error loading Ruffle: ${e}`),"file:"===window.location.protocol)e.ruffleIndexError=et.FileProtocol;else{e.ruffleIndexError=et.WasmNotFound;const n=String(e.message).toLowerCase();n.includes("mime")?e.ruffleIndexError=et.WasmMimeType:n.includes("networkerror")||n.includes("failed to fetch")?e.ruffleIndexError=et.WasmCors:n.includes("disallowed by embedder")?e.ruffleIndexError=et.CSPConflict:"CompileError"===e.name?e.ruffleIndexError=et.InvalidWasm:n.includes("could not download wasm module")&&"TypeError"===e.name?e.ruffleIndexError=et.WasmDownload:"TypeError"===e.name?e.ruffleIndexError=et.JavascriptConflict:navigator.userAgent.includes("Edg")&&n.includes("webassembly is not defined")&&(e.ruffleIndexError=et.WasmDisabledMicrosoftEdge)}throw this.panic(e),e})),null===(e=this.loadedConfig)||void 0===e?void 0:e.fontSources)for(const e of this.loadedConfig.fontSources)try{const n=await fetch(e);this.instance.add_font(e,new Uint8Array(await n.arrayBuffer()))}catch(n){console.warn(`Couldn't download font source from ${e}`,n)}(null===(t=null===(n=this.loadedConfig)||void 0===n?void 0:n.defaultFonts)||void 0===t?void 0:t.sans)&&this.instance.set_default_font("sans",null===(r=this.loadedConfig)||void 0===r?void 0:r.defaultFonts.sans),(null===(i=null===(a=this.loadedConfig)||void 0===a?void 0:a.defaultFonts)||void 0===i?void 0:i.serif)&&this.instance.set_default_font("serif",null===(o=this.loadedConfig)||void 0===o?void 0:o.defaultFonts.serif),(null===(l=null===(s=this.loadedConfig)||void 0===s?void 0:s.defaultFonts)||void 0===l?void 0:l.typewriter)&&this.instance.set_default_font("typewriter",null===(u=this.loadedConfig)||void 0===u?void 0:u.defaultFonts.typewriter),this.instance.set_volume(this.volumeSettings.get_volume()),this.rendererDebugInfo=this.instance.renderer_debug_info(),this.rendererDebugInfo.includes("Adapter Device Type: Cpu")&&this.container.addEventListener("mouseover",this.openHardwareAccelerationModal.bind(this),{once:!0});const d=this.instance.renderer_name(),f=this.instance.constructor;if(console.log("%cNew Ruffle instance created (Version: "+Vn.versionName+" | WebAssembly extensions: "+(f.is_wasm_simd_used()?"ON":"OFF")+" | Used renderer: "+(null!=d?d:"")+")","background: #37528C; color: #FFAD33"),"running"!==this.audioState()&&(this.container.style.visibility="hidden",await new Promise((e=>{window.setTimeout((()=>{e()}),200)})),this.container.style.visibility=""),this.unmuteAudioContext(),navigator.userAgent.toLowerCase().includes("android")&&this.container.addEventListener("click",(()=>this.virtualKeyboard.blur())),!this.loadedConfig||this.loadedConfig.autoplay===Fn.On||this.loadedConfig.autoplay!==Fn.Off&&"running"===this.audioState()){if(this.play(),"running"!==this.audioState()){this.loadedConfig&&this.loadedConfig.unmuteOverlay===Dn.Hidden||(this.unmuteOverlay.style.display="block"),this.container.addEventListener("click",this.unmuteOverlayClicked.bind(this),{once:!0});const e=null===(c=this.instance)||void 0===c?void 0:c.audio_context();e&&(e.onstatechange=()=>{"running"===e.state&&this.unmuteOverlayClicked(),e.onstatechange=null})}}else this.playButton.style.display="block"}onRuffleDownloadProgress(e,n){const t=this.splashScreen.querySelector(".loadbar-inner"),r=this.splashScreen.querySelector(".loadbar");Number.isNaN(n)?r&&(r.style.display="none"):t.style.width=e/n*100+"%"}destroy(){this.instance&&(this.instance.destroy(),this.instance=null,this._metadata=null,this._readyState=nt.HaveNothing,console.log("Ruffle instance destroyed."))}checkOptions(e){if("string"==typeof e)return{url:e};const n=(e,n)=>{if(!e){const e=new TypeError(n);throw e.ruffleIndexError=et.JavascriptConfiguration,this.panic(e),e}};return n(null!==e&&"object"==typeof e,"Argument 0 must be a string or object"),n("url"in e||"data"in e,"Argument 0 must contain a `url` or `data` key"),n(!("url"in e)||"string"==typeof e.url,"`url` must be a string"),e}async reload(){if(!this.loadedConfig)throw new Error("Cannot reload if load wasn't first called");await this.load(this.loadedConfig)}async load(e,n=!1){var t,r;if(e=this.checkOptions(e),this.isConnected&&!this.isUnusedFallbackObject()){if(!ct(this))try{this.loadedConfig=Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},$n),n&&"url"in e?{allowScriptAccess:ot("samedomain",e.url)}:{}),null!==(r=null===(t=window.RufflePlayer)||void 0===t?void 0:t.config)&&void 0!==r?r:{}),this.config),e),this.loadedConfig.backgroundColor&&this.loadedConfig.wmode!==Tn.Transparent&&(this.container.style.backgroundColor=this.loadedConfig.backgroundColor),await this.ensureFreshInstance(),"url"in e?(console.log(`Loading SWF file ${e.url}`),this.swfUrl=new URL(e.url,document.baseURI),this.instance.stream_from(this.swfUrl.href,tt(e.parameters))):"data"in e&&(console.log("Loading SWF data"),this.instance.load_data(new Uint8Array(e.data),tt(e.parameters),e.swfFileName||"movie.swf"))}catch(e){console.error(`Serious error occurred loading SWF file: ${e}`);const n=new Error(e);throw n.message.includes("Error parsing config")&&(n.ruffleIndexError=et.JavascriptConfiguration),this.panic(n),n}}else console.warn("Ignoring attempt to play a disconnected or suspended Ruffle element")}play(){this.instance&&(this.instance.play(),this.playButton.style.display="none")}get isPlaying(){return!!this.instance&&this.instance.is_playing()}get volume(){return this.instance?this.instance.volume():1}set volume(e){this.instance&&this.instance.set_volume(e)}get fullscreenEnabled(){return!(!document.fullscreenEnabled&&!document.webkitFullscreenEnabled)}get isFullscreen(){return(document.fullscreenElement||document.webkitFullscreenElement)===this}setFullscreen(e){this.fullscreenEnabled&&e!==this.isFullscreen&&(e?this.enterFullscreen():this.exitFullscreen())}enterFullscreen(){const e={navigationUI:"hide"};this.requestFullscreen?this.requestFullscreen(e):this.webkitRequestFullscreen?this.webkitRequestFullscreen(e):this.webkitRequestFullScreen&&this.webkitRequestFullScreen(e)}exitFullscreen(){document.exitFullscreen?document.exitFullscreen():document.webkitExitFullscreen?document.webkitExitFullscreen():document.webkitCancelFullScreen&&document.webkitCancelFullScreen()}fullScreenChange(){var e;null===(e=this.instance)||void 0===e||e.set_fullscreen(this.isFullscreen)}saveFile(e,n){const t=URL.createObjectURL(e),r=document.createElement("a");r.href=t,r.style.display="none",r.download=n,document.body.appendChild(r),r.click(),document.body.removeChild(r),URL.revokeObjectURL(t)}checkIfTouch(e){this.isTouch="touch"===e.pointerType||"pen"===e.pointerType}base64ToBlob(e,n){const t=atob(e),r=new ArrayBuffer(t.length),a=new Uint8Array(r);for(let e=0;e{if(r.result&&"string"==typeof r.result){const e=new RegExp("data:.*;base64,"),t=r.result.replace(e,"");this.confirmReloadSave(n,t,!0)}})),t&&t.files&&t.files.length>0&&t.files[0]&&r.readAsDataURL(t.files[0])}deleteSave(e){const n=localStorage.getItem(e);n&&this.confirmReloadSave(e,n,!1)}populateSaves(){const e=this.saveManager.querySelector("#local-saves");if(e){try{if(null===localStorage)return}catch(e){return}e.textContent="",Object.keys(localStorage).forEach((n=>{const t=n.split("/").pop(),r=localStorage.getItem(n);if(t&&r&&this.isB64SOL(r)){const a=document.createElement("TR"),i=document.createElement("TD");i.textContent=t,i.title=n;const o=document.createElement("TD"),s=document.createElement("SPAN");s.textContent=ve("save-download"),s.className="save-option",s.addEventListener("click",(()=>{const e=this.base64ToBlob(r,"application/octet-stream");this.saveFile(e,t+".sol")})),o.appendChild(s);const l=document.createElement("TD"),u=document.createElement("INPUT");u.type="file",u.accept=".sol",u.className="replace-save",u.id="replace-save-"+n;const c=document.createElement("LABEL");c.htmlFor="replace-save-"+n,c.textContent=ve("save-replace"),c.className="save-option",u.addEventListener("change",(e=>this.replaceSOL(e,n))),l.appendChild(u),l.appendChild(c);const d=document.createElement("TD"),f=document.createElement("SPAN");f.textContent=ve("save-delete"),f.className="save-option",f.addEventListener("click",(()=>this.deleteSave(n))),d.appendChild(f),a.appendChild(i),a.appendChild(o),a.appendChild(l),a.appendChild(d),e.appendChild(a)}}))}}async backupSaves(){const e=new(Gn()),n=[];Object.keys(localStorage).forEach((t=>{let r=String(t.split("/").pop());const a=localStorage.getItem(t);if(a&&this.isB64SOL(a)){const t=this.base64ToBlob(a,"application/octet-stream"),i=n.filter((e=>e===r)).length;n.push(r),i>0&&(r+=` (${i+1})`),e.file(r+".sol",t)}}));const t=await e.generateAsync({type:"blob"});this.saveFile(t,"saves.zip")}openHardwareAccelerationModal(){this.hardwareAccelerationModal.classList.remove("hidden")}openSaveManager(){this.saveManager.classList.remove("hidden")}openVolumeControls(){this.volumeControls.classList.remove("hidden")}async downloadSwf(){try{if(this.swfUrl){console.log("Downloading SWF: "+this.swfUrl);const e=await fetch(this.swfUrl.href);if(!e.ok)return void console.error("SWF download failed");const n=await e.blob();this.saveFile(n,function(e){const n=e.pathname;return n.substring(n.lastIndexOf("/")+1)}(this.swfUrl))}else console.error("SWF download failed")}catch(e){console.error("SWF download failed")}}virtualKeyboardInput(){const e=this.virtualKeyboard,n=e.value;for(const e of n)for(const n of["keydown","keyup"])this.dispatchEvent(new KeyboardEvent(n,{key:e,bubbles:!0}));e.value=""}openVirtualKeyboard(){navigator.userAgent.toLowerCase().includes("android")?setTimeout((()=>{this.virtualKeyboard.focus({preventScroll:!0})}),100):this.virtualKeyboard.focus({preventScroll:!0})}isVirtualKeyboardFocused(){return this.shadow.activeElement===this.virtualKeyboard}contextMenuItems(){const e=String.fromCharCode(10003),n=[],t=()=>{n.length>0&&null!==n[n.length-1]&&n.push(null)};if(this.instance&&this.isPlaying){this.instance.prepare_context_menu().forEach(((r,a)=>{r.separatorBefore&&t(),n.push({text:r.caption+(r.checked?` (${e})`:""),onClick:()=>{var e;return null===(e=this.instance)||void 0===e?void 0:e.run_context_menu_callback(a)},enabled:r.enabled})})),t()}this.fullscreenEnabled&&(this.isFullscreen?n.push({text:ve("context-menu-exit-fullscreen"),onClick:()=>{var e;return null===(e=this.instance)||void 0===e?void 0:e.set_fullscreen(!1)}}):n.push({text:ve("context-menu-enter-fullscreen"),onClick:()=>{var e;return null===(e=this.instance)||void 0===e?void 0:e.set_fullscreen(!0)}})),n.push({text:ve("context-menu-volume-controls"),onClick:()=>{this.openVolumeControls()}}),this.instance&&this.swfUrl&&this.loadedConfig&&!0===this.loadedConfig.showSwfDownload&&(t(),n.push({text:ve("context-menu-download-swf"),onClick:this.downloadSwf.bind(this)})),navigator.clipboard&&window.isSecureContext&&n.push({text:ve("context-menu-copy-debug-info"),onClick:()=>navigator.clipboard.writeText(this.getPanicData())}),this.populateSaves();const r=this.saveManager.querySelector("#local-saves");return r&&""!==r.textContent&&n.push({text:ve("context-menu-open-save-manager"),onClick:this.openSaveManager.bind(this)}),t(),n.push({text:ve("context-menu-about-ruffle",{flavor:d?"extension":"",version:Vn.versionName}),onClick(){window.open(Yn,"_blank")}}),this.isTouch&&(t(),n.push({text:ve("context-menu-hide"),onClick:()=>this.contextMenuForceDisabled=!0})),n}pointerDown(e){this.pointerDownPosition=new rt(e.pageX,e.pageY),this.pointerMoveMaxDistance=0,this.startLongPressTimer()}clearLongPressTimer(){this.longPressTimer&&(clearTimeout(this.longPressTimer),this.longPressTimer=null)}startLongPressTimer(){this.clearLongPressTimer(),this.longPressTimer=setTimeout((()=>this.clearLongPressTimer()),800)}checkLongPressMovement(e){if(null!==this.pointerDownPosition){const n=new rt(e.pageX,e.pageY),t=this.pointerDownPosition.distanceTo(n);t>this.pointerMoveMaxDistance&&(this.pointerMoveMaxDistance=t)}}checkLongPress(e){this.longPressTimer?this.clearLongPressTimer():!this.contextMenuSupported&&"mouse"!==e.pointerType&&this.pointerMoveMaxDistance<15&&this.showContextMenu(e)}showContextMenu(e){var n,t,r;const a=Array.from(this.shadow.querySelectorAll(".modal")).some((e=>!e.classList.contains("hidden")));if(this.panicked||a)return;if(e.preventDefault(),"contextmenu"===e.type?(this.contextMenuSupported=!0,document.documentElement.addEventListener("click",this.hideContextMenu.bind(this),{once:!0})):(document.documentElement.addEventListener("pointerup",this.hideContextMenu.bind(this),{once:!0}),e.stopPropagation()),[!1,Mn.Off].includes(null!==(t=null===(n=this.loadedConfig)||void 0===n?void 0:n.contextMenu)&&void 0!==t?t:Mn.On)||this.isTouch&&(null===(r=this.loadedConfig)||void 0===r?void 0:r.contextMenu)===Mn.RightClickOnly||this.contextMenuForceDisabled)return;for(;this.contextMenuElement.firstChild;)this.contextMenuElement.removeChild(this.contextMenuElement.firstChild);for(const e of this.contextMenuItems())if(null===e){const e=document.createElement("li");e.className="menu-separator";const n=document.createElement("hr");e.appendChild(n),this.contextMenuElement.appendChild(e)}else{const{text:n,onClick:t,enabled:r}=e,a=document.createElement("li");a.className="menu-item",a.textContent=n,this.contextMenuElement.appendChild(a),!1!==r?a.addEventListener(this.contextMenuSupported?"click":"pointerup",t):a.classList.add("disabled")}this.contextMenuElement.style.left="0",this.contextMenuElement.style.top="0",this.contextMenuOverlay.classList.remove("hidden");const i=this.getBoundingClientRect(),o=e.clientX-i.x,s=e.clientY-i.y,l=i.width-this.contextMenuElement.clientWidth-1,u=i.height-this.contextMenuElement.clientHeight-1;this.contextMenuElement.style.left=Math.floor(Math.min(o,l))+"px",this.contextMenuElement.style.top=Math.floor(Math.min(s,u))+"px"}hideContextMenu(){var e;null===(e=this.instance)||void 0===e||e.clear_custom_menu_items(),this.contextMenuOverlay.classList.add("hidden")}pause(){this.instance&&(this.instance.pause(),this.playButton.style.display="block")}audioState(){if(this.instance){const e=this.instance.audio_context();return e&&e.state||"running"}return"suspended"}unmuteOverlayClicked(){if(this.instance){if("running"!==this.audioState()){const e=this.instance.audio_context();e&&e.resume()}this.unmuteOverlay.style.display="none"}}unmuteAudioContext(){Qn||(navigator.maxTouchPoints<1?Qn=!0:this.container.addEventListener("click",(()=>{var e;if(Qn)return;const n=null===(e=this.instance)||void 0===e?void 0:e.audio_context();if(!n)return;const t=new Audio;t.src=(()=>{const e=new ArrayBuffer(10),t=new DataView(e),r=n.sampleRate;t.setUint32(0,r,!0),t.setUint32(4,r,!0),t.setUint16(8,1,!0);return`data:audio/wav;base64,UklGRisAAABXQVZFZm10IBAAAAABAAEA${window.btoa(String.fromCharCode(...new Uint8Array(e))).slice(0,13)}AgAZGF0YQcAAACAgICAgICAAAA=`})(),t.load(),t.play().then((()=>{Qn=!0})).catch((e=>{console.warn(`Failed to play dummy sound: ${e}`)}))}),{once:!0}))}copyElement(e){if(e){for(const n of e.attributes)if(n.specified){if("title"===n.name&&"Adobe Flash Player"===n.value)continue;try{this.setAttribute(n.name,n.value)}catch(e){console.warn(`Unable to set attribute ${n.name} on Ruffle instance`)}}for(const n of Array.from(e.children))this.appendChild(n)}}static htmlDimensionToCssDimension(e){if(e){const n=e.match(Xn);if(n){let e=n[1];return n[3]||(e+="px"),e}}return null}onCallbackAvailable(e){const n=this.instance;this[e]=(...t)=>null==n?void 0:n.call_exposed_callback(e,t)}set traceObserver(e){var n;null===(n=this.instance)||void 0===n||n.set_trace_observer(e)}getPanicData(){let e="\n# Player Info\n";if(e+=`Allows script access: ${!!this.loadedConfig&&this.loadedConfig.allowScriptAccess}\n`,e+=`${this.rendererDebugInfo}\n`,e+=this.debugPlayerInfo(),e+="\n# Page Info\n",e+=`Page URL: ${document.location.href}\n`,this.swfUrl&&(e+=`SWF URL: ${this.swfUrl}\n`),e+="\n# Browser Info\n",e+=`User Agent: ${window.navigator.userAgent}\n`,e+=`Platform: ${window.navigator.platform}\n`,e+=`Has touch support: ${window.navigator.maxTouchPoints>0}\n`,e+="\n# Ruffle Info\n",e+=`Version: ${Vn.versionNumber}\n`,e+=`Name: ${Vn.versionName}\n`,e+=`Channel: ${Vn.versionChannel}\n`,e+=`Built: ${Vn.buildDate}\n`,e+=`Commit: ${Vn.commitHash}\n`,e+=`Is extension: ${d}\n`,e+="\n# Metadata\n",this.metadata)for(const[n,t]of Object.entries(this.metadata))e+=`${n}: ${t}\n`;return e}createErrorFooter(e){const n=document.createElement("ul");for(const t of e){const e=document.createElement("li"),r=document.createElement("a");r.href=t.url,r.textContent=t.label,"#"===t.url?r.id="panic-view-details":r.target="_top",e.appendChild(r),n.appendChild(e)}return n}panic(e){var n;if(this.panicked)return;if(this.panicked=!0,this.hideSplashScreen(),e instanceof Error&&("AbortError"===e.name||e.message.includes("AbortError")))return;const t=null!==(n=null==e?void 0:e.ruffleIndexError)&&void 0!==n?n:et.Unknown,r=Object.assign([],{stackIndex:-1,avmStackIndex:-1});if(r.push("# Error Info\n"),e instanceof Error){if(r.push(`Error name: ${e.name}\n`),r.push(`Error message: ${e.message}\n`),e.stack){const n=r.push(`Error stack:\n\`\`\`\n${e.stack}\n\`\`\`\n`)-1;if(e.avmStack){const n=r.push(`AVM2 stack:\n\`\`\`\n ${e.avmStack.trim().replace(/\t/g," ")}\n\`\`\`\n`)-1;r.avmStackIndex=n}r.stackIndex=n}}else r.push(`Error: ${e}\n`);r.push(this.getPanicData());const a=r.join(""),i=new Date(Vn.buildDate),o=new Date;o.setMonth(o.getMonth()-6);const s=o>i;let l,u,c;if(s)l=new at(Yn+"#downloads",ve("update-ruffle"));else{let e;e=document.location.protocol.includes("extension")?this.swfUrl.href:document.location.href,e=e.split(/[?#]/,1)[0];let n=`https://github.com/ruffle-rs/ruffle/issues/new?title=${encodeURIComponent(`Error on ${e}`)}&template=error_report.md&labels=error-report&body=`,t=encodeURIComponent(a);r.stackIndex>-1&&String(n+t).length>8195&&(r[r.stackIndex]=null,r.avmStackIndex>-1&&(r[r.avmStackIndex]=null),t=encodeURIComponent(r.join(""))),n+=t,l=new at(n,ve("report-bug"))}switch(t){case et.FileProtocol:u=ge("error-file-protocol"),c=this.createErrorFooter([new at(Yn+"/demo",ve("ruffle-demo")),new at(Yn+"#downloads",ve("ruffle-desktop"))]);break;case et.JavascriptConfiguration:u=ge("error-javascript-config"),c=this.createErrorFooter([new at("https://github.com/ruffle-rs/ruffle/wiki/Using-Ruffle#javascript-api",ve("ruffle-wiki")),new at]);break;case et.WasmNotFound:u=ge("error-wasm-not-found"),c=this.createErrorFooter([new at("https://github.com/ruffle-rs/ruffle/wiki/Using-Ruffle#configuration-options",ve("ruffle-wiki")),new at]);break;case et.WasmMimeType:u=ge("error-wasm-mime-type"),c=this.createErrorFooter([new at("https://github.com/ruffle-rs/ruffle/wiki/Using-Ruffle#configure-webassembly-mime-type",ve("ruffle-wiki")),new at]);break;case et.SwfFetchError:u=ge("error-swf-fetch"),c=this.createErrorFooter([new at]);break;case et.SwfCors:u=ge("error-swf-cors"),c=this.createErrorFooter([new at("https://github.com/ruffle-rs/ruffle/wiki/Using-Ruffle#configure-cors-header",ve("ruffle-wiki")),new at]);break;case et.WasmCors:u=ge("error-wasm-cors"),c=this.createErrorFooter([new at("https://github.com/ruffle-rs/ruffle/wiki/Using-Ruffle#configure-cors-header",ve("ruffle-wiki")),new at]);break;case et.InvalidWasm:u=ge("error-wasm-invalid"),c=this.createErrorFooter([new at("https://github.com/ruffle-rs/ruffle/wiki/Using-Ruffle#addressing-a-compileerror",ve("ruffle-wiki")),new at]);break;case et.WasmDownload:u=ge("error-wasm-download"),c=this.createErrorFooter([new at]);break;case et.WasmDisabledMicrosoftEdge:u=ge("error-wasm-disabled-on-edge"),c=this.createErrorFooter([new at("https://github.com/ruffle-rs/ruffle/wiki/Frequently-Asked-Questions-For-Users#edge-webassembly-error",ve("more-info")),new at]);break;case et.JavascriptConflict:u=ge("error-javascript-conflict"),s&&u.appendChild(ge("error-javascript-conflict-outdated",{buildDate:Vn.buildDate})),c=this.createErrorFooter([l,new at]);break;case et.CSPConflict:u=ge("error-csp-conflict"),c=this.createErrorFooter([new at("https://github.com/ruffle-rs/ruffle/wiki/Using-Ruffle#configure-wasm-csp",ve("ruffle-wiki")),new at]);break;default:u=ge("error-unknown",{buildDate:Vn.buildDate,outdated:String(s)}),c=this.createErrorFooter([l,new at])}const d=document.createElement("div");d.id="panic";const f=document.createElement("div");f.id="panic-title",f.textContent=ve("panic-title"),d.appendChild(f);const m=document.createElement("div");m.id="panic-body",m.appendChild(u),d.appendChild(m);const h=document.createElement("div");h.id="panic-footer",h.appendChild(c),d.appendChild(h),this.container.textContent="",this.container.appendChild(d);const p=this.container.querySelector("#panic-view-details");p&&(p.onclick=()=>{const e=this.container.querySelector("#panic-body");e.classList.add("details");const n=document.createElement("textarea");return n.readOnly=!0,n.value=a,e.replaceChildren(n),!1}),this.destroy()}displayRootMovieDownloadFailedMessage(){var e,n,t;const r=null===(e=this.loadedConfig)||void 0===e?void 0:e.openInNewTab;if(r&&window.location.origin!==this.swfUrl.origin){const e=new URL(this.swfUrl);if(null===(n=this.loadedConfig)||void 0===n?void 0:n.parameters){const n=tt(null===(t=this.loadedConfig)||void 0===t?void 0:t.parameters);Object.entries(n).forEach((([n,t])=>{e.searchParams.set(n,t)}))}this.hideSplashScreen();const a=document.createElement("div");a.id="message-overlay";const i=document.createElement("div");i.className="message",i.appendChild(ge("message-cant-embed"));const o=document.createElement("div"),s=document.createElement("a");s.innerText=ve("open-in-new-tab"),s.onclick=()=>r(e),o.appendChild(s),i.appendChild(o),a.appendChild(i),this.container.prepend(a)}else{const e=new Error("Failed to fetch: "+this.swfUrl);this.swfUrl.protocol.includes("http")?window.location.origin===this.swfUrl.origin||window.location.protocol.includes("extension")?e.ruffleIndexError=et.SwfFetchError:e.ruffleIndexError=et.SwfCors:e.ruffleIndexError=et.FileProtocol,this.panic(e)}}displayMessage(e){const n=document.createElement("div");n.id="message-overlay";const t=document.createElement("div");t.className="message";const r=document.createElement("p");r.textContent=e,t.appendChild(r);const a=document.createElement("div"),i=document.createElement("button");i.id="continue-btn",i.textContent=ve("continue"),a.appendChild(i),t.appendChild(a),n.appendChild(t),this.container.prepend(n),this.container.querySelector("#continue-btn").onclick=()=>{n.parentNode.removeChild(n)}}displayUnsupportedVideo(e){const n=this.videoModal.querySelector("#video-holder");if(n){const t=document.createElement("video");t.addEventListener("contextmenu",(e=>e.stopPropagation())),t.src=e,t.autoplay=!0,t.controls=!0,n.textContent="",n.appendChild(t),this.videoModal.classList.remove("hidden")}}debugPlayerInfo(){return""}hideSplashScreen(){this.splashScreen.classList.add("hidden"),this.container.classList.remove("hidden")}showSplashScreen(){this.splashScreen.classList.remove("hidden"),this.container.classList.add("hidden")}setMetadata(e){this._metadata=e,this._readyState=nt.Loaded,this.hideSplashScreen(),this.dispatchEvent(new CustomEvent(it.LOADED_METADATA)),this.dispatchEvent(new CustomEvent(it.LOADED_DATA))}}function ot(e,n){switch(null==e?void 0:e.toLowerCase()){case"always":return!0;case"never":return!1;case"samedomain":try{return new URL(window.location.href).origin===new URL(n,window.location.href).origin}catch(e){return!1}default:return null}}function st(e,n){const t={url:e},r=n("allowNetworking");null!==r&&(t.allowNetworking=r);const a=ot(n("allowScriptAccess"),e);null!==a&&(t.allowScriptAccess=a);const i=n("bgcolor");null!==i&&(t.backgroundColor=i);const o=n("base");null!==o&&(t.base=o);const s=function(e){switch(null==e?void 0:e.toLowerCase()){case"true":return!0;case"false":return!1;default:return null}}(n("menu"));null!==s&&(t.menu=s);const l=n("flashvars");null!==l&&(t.parameters=l);const u=n("quality");null!==u&&(t.quality=u);const c=n("salign");null!==c&&(t.salign=c);const d=n("scale");null!==d&&(t.scale=d);const f=n("wmode");return null!==f&&(t.wmode=f),t}function lt(e){if(e){let n="",t="";try{const r=new URL(e,Yn);n=r.pathname,t=r.hostname}catch(e){}if(n.startsWith("/v/")&&/^(?:(?:www\.|m\.)?youtube(?:-nocookie)?\.com)|(?:youtu\.be)$/i.test(t))return!0}return!1}function ut(e,n){var t,r;const a=e.getAttribute(n),i=null!==(r=null===(t=window.RufflePlayer)||void 0===t?void 0:t.config)&&void 0!==r?r:{};if(a)try{const t=new URL(a);"http:"!==t.protocol||"https:"!==window.location.protocol||"upgradeToHttps"in i&&!1===i.upgradeToHttps||(t.protocol="https:",e.setAttribute(n,t.toString()))}catch(e){}}function ct(e){let n=e.parentElement;for(;null!==n;){switch(n.tagName){case"AUDIO":case"VIDEO":return!0}n=n.parentElement}return!1}it.LOADED_METADATA="loadedmetadata",it.LOADED_DATA="loadeddata",function(e){e[e.HaveNothing=0]="HaveNothing",e[e.Loading=1]="Loading",e[e.Loaded=2]="Loaded"}(nt||(nt={}));class dt{constructor(e,n){this.isMuted=e,this.volume=n}get_volume(){return this.isMuted?0:this.volume/100}}class ft extends it{constructor(){super()}connectedCallback(){super.connectedCallback();const e=this.attributes.getNamedItem("src");if(e){const n=e=>{var n,t;return null!==(t=null===(n=this.attributes.getNamedItem(e))||void 0===n?void 0:n.value)&&void 0!==t?t:null},t=st(e.value,n);this.load(t,!0)}}get src(){var e;return null===(e=this.attributes.getNamedItem("src"))||void 0===e?void 0:e.value}set src(e){if(e){const n=document.createAttribute("src");n.value=e,this.attributes.setNamedItem(n)}else this.attributes.removeNamedItem("src")}static get observedAttributes(){return["src","width","height"]}attributeChangedCallback(e,n,t){if(super.attributeChangedCallback(e,n,t),this.isConnected&&"src"===e){const e=this.attributes.getNamedItem("src");if(e){const n=e=>{var n,t;return null!==(t=null===(n=this.attributes.getNamedItem(e))||void 0===n?void 0:n.value)&&void 0!==t?t:null},t=st(e.value,n);this.load(t,!0)}}}static isInterdictable(e){const n=e.getAttribute("src"),t=e.getAttribute("type");return!!n&&(!ct(e)&&(lt(n)?(ut(e,"src"),!1):Jn(n,t)))}static fromNativeEmbedElement(e){const n=In("ruffle-embed",ft),t=document.createElement(n);return t.copyElement(e),t}}function mt(e){var n,t;const r={};for(const a of e.children)if(a instanceof HTMLParamElement){const e=null===(n=a.attributes.getNamedItem("name"))||void 0===n?void 0:n.value,i=null===(t=a.attributes.getNamedItem("value"))||void 0===t?void 0:t.value;e&&i&&(r[e]=i)}return r}class ht extends it{constructor(){super(),this.params={}}connectedCallback(){var e;super.connectedCallback(),this.params=mt(this);let n=null;if(this.attributes.getNamedItem("data")?n=null===(e=this.attributes.getNamedItem("data"))||void 0===e?void 0:e.value:this.params.movie&&(n=this.params.movie),n){const e=["allowNetworking","base","bgcolor","flashvars"],t=st(n,(n=>function(e,n,t){n=n.toLowerCase();for(const[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r;return t}(this.params,n,e.includes(n)?this.getAttribute(n):null)));this.load(t,!0)}}debugPlayerInfo(){var e;let n="Player type: Object\n",t=null;return this.attributes.getNamedItem("data")?t=null===(e=this.attributes.getNamedItem("data"))||void 0===e?void 0:e.value:this.params.movie&&(t=this.params.movie),n+=`SWF URL: ${t}\n`,Object.keys(this.params).forEach((e=>{n+=`Param ${e}: ${this.params[e]}\n`})),Object.keys(this.attributes).forEach((e=>{var t;n+=`Attribute ${e}: ${null===(t=this.attributes.getNamedItem(e))||void 0===t?void 0:t.value}\n`})),n}get data(){return this.getAttribute("data")}set data(e){if(e){const n=document.createAttribute("data");n.value=e,this.attributes.setNamedItem(n)}else this.attributes.removeNamedItem("data")}static isInterdictable(e){var n,t,r,a;if(ct(e))return!1;if(e.getElementsByTagName("ruffle-object").length>0||e.getElementsByTagName("ruffle-embed").length>0)return!1;const i=null===(n=e.attributes.getNamedItem("data"))||void 0===n?void 0:n.value.toLowerCase(),o=null!==(r=null===(t=e.attributes.getNamedItem("type"))||void 0===t?void 0:t.value)&&void 0!==r?r:null,s=mt(e);let l;if(i){if(lt(i))return ut(e,"data"),!1;l=i}else{if(!s||!s.movie)return!1;if(lt(s.movie)){const n=e.querySelector("param[name='movie']");if(n){ut(n,"value");const t=n.getAttribute("value");t&&e.setAttribute("data",t)}return!1}l=s.movie}const u=null===(a=e.attributes.getNamedItem("classid"))||void 0===a?void 0:a.value.toLowerCase();return u==="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000".toLowerCase()?!Array.from(e.getElementsByTagName("object")).some(ht.isInterdictable)&&!Array.from(e.getElementsByTagName("embed")).some(ft.isInterdictable):!u&&Jn(l,o)}static fromNativeObjectElement(e){const n=In("ruffle-object",ht),t=document.createElement(n);for(const n of Array.from(e.getElementsByTagName("embed")))ft.isInterdictable(n)&&n.remove();for(const n of Array.from(e.getElementsByTagName("object")))ht.isInterdictable(n)&&n.remove();return t.copyElement(e),t}}class pt{constructor(e){if(this.__mimeTypes=[],this.__namedMimeTypes={},e)for(let n=0;n>>0]}namedItem(e){return this.__namedMimeTypes[e]}get length(){return this.__mimeTypes.length}[Symbol.iterator](){return this.__mimeTypes[Symbol.iterator]()}}class vt{constructor(e){this.__plugins=[],this.__namedPlugins={};for(let n=0;n>>0]}namedItem(e){return this.__namedPlugins[e]}refresh(){}[Symbol.iterator](){return this.__plugins[Symbol.iterator]()}get length(){return this.__plugins.length}}const gt=new class extends pt{constructor(e,n,t){super(),this.name=e,this.description=n,this.filename=t}}("Shockwave Flash","Shockwave Flash 32.0 r0","ruffle.js");var bt,wt;gt.install({type:Un,description:"Shockwave Flash",suffixes:"spl",enabledPlugin:gt}),gt.install({type:Nn,description:"Shockwave Flash",suffixes:"swf",enabledPlugin:gt}),gt.install({type:Zn,description:"Shockwave Flash",suffixes:"swf",enabledPlugin:gt}),gt.install({type:Hn,description:"Shockwave Flash",suffixes:"swf",enabledPlugin:gt});const kt=null!==(wt=null===(bt=window.RufflePlayer)||void 0===bt?void 0:bt.config)&&void 0!==wt?wt:{},yt=f(kt)+"ruffle.js";let xt,Rt,_t,zt;function St(){var e,n;return(!("favorFlash"in kt)||!1!==kt.favorFlash)&&"ruffle.js"!==(null!==(n=null===(e=navigator.plugins.namedItem("Shockwave Flash"))||void 0===e?void 0:e.filename)&&void 0!==n?n:"ruffle.js")}function jt(){try{xt=null!=xt?xt:document.getElementsByTagName("object"),Rt=null!=Rt?Rt:document.getElementsByTagName("embed");for(const e of Array.from(xt))if(ht.isInterdictable(e)){const n=ht.fromNativeObjectElement(e);e.replaceWith(n)}for(const e of Array.from(Rt))if(ft.isInterdictable(e)){const n=ft.fromNativeEmbedElement(e);e.replaceWith(n)}}catch(e){console.error(`Serious error encountered when polyfilling native Flash elements: ${e}`)}}function Et(){_t=null!=_t?_t:document.getElementsByTagName("iframe"),zt=null!=zt?zt:document.getElementsByTagName("frame"),[_t,zt].forEach((e=>{for(const n of e){if(void 0!==n.dataset.rufflePolyfilled)continue;n.dataset.rufflePolyfilled="";const e=n.contentWindow,t=`Couldn't load Ruffle into ${n.tagName}[${n.src}]: `;try{"complete"===e.document.readyState&&Ct(e,t)}catch(e){d||console.warn(t+e)}n.addEventListener("load",(()=>{Ct(e,t)}),!1)}}))}async function Ct(e,n){var t;let r;await new Promise((e=>{window.setTimeout((()=>{e()}),100)}));try{if(r=e.document,!r)return}catch(e){return void(d||console.warn(n+e))}if(d||void 0===r.documentElement.dataset.ruffleOptout)if(d)e.RufflePlayer||(e.RufflePlayer={}),e.RufflePlayer.config=Object.assign(Object.assign({},kt),null!==(t=e.RufflePlayer.config)&&void 0!==t?t:{});else if(!e.RufflePlayer){const n=r.createElement("script");n.setAttribute("src",yt),n.onload=()=>{e.RufflePlayer={},e.RufflePlayer.config=kt},r.head.appendChild(n)}}function At(){St()||function(e){"install"in navigator.plugins&&navigator.plugins.install||Object.defineProperty(navigator,"plugins",{value:new vt(navigator.plugins),writable:!1}),navigator.plugins.install(e),!(e.length>0)||"install"in navigator.mimeTypes&&navigator.mimeTypes.install||Object.defineProperty(navigator,"mimeTypes",{value:new pt(navigator.mimeTypes),writable:!1});const n=navigator.mimeTypes;for(let t=0;tArray.from(e.addedNodes).some((e=>["EMBED","OBJECT"].includes(e.nodeName)||e instanceof Element&&null!==e.querySelector("embed, object")))))&&(jt(),Et())})).observe(document,{childList:!0,subtree:!0}))}const Ft={version:Vn.versionNumber+"+"+Vn.buildDate.substring(0,10),polyfill(){It()},pluginPolyfill(){At()},createPlayer(){const e=In("ruffle-player",it);return document.createElement(e)}};class Ot{constructor(e){var n;this.sources=(null==e?void 0:e.sources)||{},this.config=(null==e?void 0:e.config)||{},this.invoked=(null==e?void 0:e.invoked)||!1,this.newestName=(null==e?void 0:e.newestName)||null,null===(n=null==e?void 0:e.superseded)||void 0===n||n.call(e),"loading"===document.readyState?document.addEventListener("readystatechange",this.init.bind(this)):window.setTimeout(this.init.bind(this),0)}get version(){return"0.1.0"}registerSource(e){this.sources[e]=Ft}newestSourceName(){let n=null,t=e.fromSemver("0.0.0");for(const r in this.sources)if(Object.prototype.hasOwnProperty.call(this.sources,r)){const a=e.fromSemver(this.sources[r].version);a.hasPrecedenceOver(t)&&(n=r,t=a)}return n}init(){if(!this.invoked){if(this.invoked=!0,this.newestName=this.newestSourceName(),null===this.newestName)throw new Error("No registered Ruffle source!");!1!==(!("polyfills"in this.config)||this.config.polyfills)&&this.sources[this.newestName].polyfill()}}newest(){const e=this.newestSourceName();return null!==e?this.sources[e]:null}satisfying(t){const r=n.fromRequirementString(t);let a=null;for(const n in this.sources)if(Object.prototype.hasOwnProperty.call(this.sources,n)){const t=e.fromSemver(this.sources[n].version);r.satisfiedBy(t)&&(a=this.sources[n])}return a}localCompatible(){return void 0!==this.sources.local?this.satisfying("^"+this.sources.local.version):this.newest()}local(){return void 0!==this.sources.local?this.satisfying("="+this.sources.local.version):this.newest()}superseded(){this.invoked=!0}static negotiate(e,n){let t;if(t=e instanceof Ot?e:new Ot(e),void 0!==n){t.registerSource(n);!1!==(!("polyfills"in t.config)||t.config.polyfills)&&Ft.pluginPolyfill()}return t}}window.RufflePlayer=Ot.negotiate(window.RufflePlayer,"local")})()})(); +//# sourceMappingURL=ruffle.js.map \ No newline at end of file diff --git a/Jake Moilanen's Linux Kernel Homepage_files/wombat.js b/Jake Moilanen's Linux Kernel Homepage_files/wombat.js new file mode 100644 index 0000000..9f2c553 --- /dev/null +++ b/Jake Moilanen's Linux Kernel Homepage_files/wombat.js @@ -0,0 +1,21 @@ +/* +Wombat.js client-side rewriting engine for web archive replay +Copyright (C) 2014-2023 Webrecorder Software, Rhizome, and Contributors. Released under the GNU Affero General Public License. + +This file is part of wombat.js, see https://github.com/webrecorder/wombat.js for the full source +Wombat.js is part of the Webrecorder project (https://github.com/webrecorder) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + */ +(function(){"use strict";function FuncMap(){this._map=[]}function ensureNumber(maybeNumber){try{switch(typeof maybeNumber){case"number":case"bigint":return maybeNumber;}var converted=Number(maybeNumber);return isNaN(converted)?null:converted}catch(e){}return null}function addToStringTagToClass(clazz,tag){typeof self.Symbol!=="undefined"&&typeof self.Symbol.toStringTag!=="undefined"&&Object.defineProperty(clazz.prototype,self.Symbol.toStringTag,{value:tag,enumerable:false})}function autobind(clazz){for(var prop,propValue,proto=clazz.__proto__||clazz.constructor.prototype||clazz.prototype,clazzProps=Object.getOwnPropertyNames(proto),len=clazzProps.length,i=0;i(r+=String.fromCharCode(n),r),""):t?t.toString():"";try{return"__wb_post_data="+btoa(e)}catch{return"__wb_post_data="}}function w(t){function o(a){return a instanceof Uint8Array&&(a=new TextDecoder().decode(a)),a}let{method:e,headers:r,postData:n}=t;if(e==="GET")return!1;let i=(r.get("content-type")||"").split(";")[0],s="";switch(i){case"application/x-www-form-urlencoded":s=o(n);break;case"application/json":s=c(o(n));break;case"text/plain":try{s=c(o(n),!1)}catch{s=u(n)}break;case"multipart/form-data":{let a=r.get("content-type");if(!a)throw new Error("utils cannot call postToGetURL when missing content-type header");s=g(o(n),a);break}default:s=u(n);}return s!==null&&(t.url=f(t.url,s,t.method),t.method="GET",t.requestBody=s,!0)}function f(t,e,r){if(!r)return t;let n=t.indexOf("?")>0?"&":"?";return`${t}${n}__wb_method=${r}&${e}`}function p(t,e=!0){if(typeof t=="string")try{t=JSON.parse(t)}catch{t={}}let r=new URLSearchParams,n={},i=o=>r.has(o)?(o in n||(n[o]=1),o+"."+ ++n[o]+"_"):o;try{JSON.stringify(t,(o,s)=>(["object","function"].includes(typeof s)||r.set(i(o),s),s))}catch(o){if(!e)throw o}return r}function y(t,e){let r=new URLSearchParams;t instanceof Uint8Array&&(t=new TextDecoder().decode(t));try{let n=e.split("boundary=")[1],i=t.split(new RegExp("-*"+n+"-*","mi"));for(let o of i){let s=o.trim().match(/name="([^"]+)"\r\n\r\n(.*)/im);s&&r.set(s[1],s[2])}}catch{}return r}function c(t,e=!0){return p(t,e).toString()}function g(t,e){return y(t,e).toString()}function Wombat($wbwindow,wbinfo){if(!(this instanceof Wombat))return new Wombat($wbwindow,wbinfo);this.debug_rw=false,this.$wbwindow=$wbwindow,this.WBWindow=Window,this.origHost=$wbwindow.location.host,this.origHostname=$wbwindow.location.hostname,this.origProtocol=$wbwindow.location.protocol,this.HTTP_PREFIX="http://",this.HTTPS_PREFIX="https://",this.REL_PREFIX="//",this.VALID_PREFIXES=[this.HTTP_PREFIX,this.HTTPS_PREFIX,this.REL_PREFIX],this.IGNORE_PREFIXES=["#","about:","data:","blob:","mailto:","javascript:","{","*"],"ignore_prefixes"in wbinfo&&(this.IGNORE_PREFIXES=this.IGNORE_PREFIXES.concat(wbinfo.ignore_prefixes)),this.WB_CHECK_THIS_FUNC="_____WB$wombat$check$this$function_____",this.WB_ASSIGN_FUNC="_____WB$wombat$assign$function_____",this.wb_setAttribute=$wbwindow.Element.prototype.setAttribute,this.wb_getAttribute=$wbwindow.Element.prototype.getAttribute,this.wb_funToString=Function.prototype.toString,this.WBAutoFetchWorker=null,this.wbUseAFWorker=wbinfo.enable_auto_fetch&&$wbwindow.Worker!=null&&wbinfo.is_live,this.wb_rel_prefix="",this.wb_wombat_updating=false,this.message_listeners=new FuncMap,this.storage_listeners=new FuncMap,this.linkAsTypes={script:"js_",worker:"js_",style:"cs_",image:"im_",document:"if_",fetch:"mp_",font:"oe_",audio:"oe_",video:"oe_",embed:"oe_",object:"oe_",track:"oe_","":"mp_",null:"mp_",undefined:"mp_"},this.linkTagMods={linkRelToAs:{import:this.linkAsTypes,preload:this.linkAsTypes},stylesheet:"cs_",null:"mp_",undefined:"mp_","":"mp_"},this.tagToMod={A:{href:"mp_"},AREA:{href:"mp_"},AUDIO:{src:"oe_",poster:"im_"},BASE:{href:"mp_"},EMBED:{src:"oe_"},FORM:{action:"mp_"},FRAME:{src:"fr_"},IFRAME:{src:"if_"},IMAGE:{href:"im_","xlink:href":"im_"},IMG:{src:"im_",srcset:"im_"},INPUT:{src:"oe_"},INS:{cite:"mp_"},META:{content:"mp_"},OBJECT:{data:"oe_",codebase:"oe_"},Q:{cite:"mp_"},SCRIPT:{src:"js_","xlink:href":"js_"},SOURCE:{src:"oe_",srcset:"oe_"},TRACK:{src:"oe_"},VIDEO:{src:"oe_",poster:"im_"},image:{href:"im_","xlink:href":"im_"}},this.URL_PROPS=["href","hash","pathname","host","hostname","protocol","origin","search","port"],this.wb_info=wbinfo,this.wb_opts=wbinfo.wombat_opts,this.wb_replay_prefix=wbinfo.prefix,this.wb_is_proxy=this.wb_info.proxy_magic||!this.wb_replay_prefix,this.wb_info.top_host=this.wb_info.top_host||"*",this.wb_curr_host=$wbwindow.location.protocol+"//"+$wbwindow.location.host,this.wb_info.wombat_opts=this.wb_info.wombat_opts||{},this.wb_orig_scheme=this.wb_info.wombat_scheme+"://",this.wb_orig_origin=this.wb_orig_scheme+this.wb_info.wombat_host,this.wb_abs_prefix=this.wb_replay_prefix,this.wb_capture_date_part="",!this.wb_info.is_live&&this.wb_info.wombat_ts&&(this.wb_capture_date_part="/"+this.wb_info.wombat_ts+"/"),this.BAD_PREFIXES=["http:"+this.wb_replay_prefix,"https:"+this.wb_replay_prefix,"http:/"+this.wb_replay_prefix,"https:/"+this.wb_replay_prefix],this.hostnamePortRe=/^[\w-]+(\.[\w-_]+)+(:\d+)(\/|$)/,this.ipPortRe=/^\d+\.\d+\.\d+\.\d+(:\d+)?(\/|$)/,this.workerBlobRe=/__WB_pmw\(.*?\)\.(?=postMessage\()/g,this.rmCheckThisInjectRe=/_____WB\$wombat\$check\$this\$function_____\(.*?\)/g,this.STYLE_REGEX=/(url\s*\(\s*[\\"']*)([^)'"]+)([\\"']*\s*\))/gi,this.IMPORT_REGEX=/(@import\s*[\\"']*)([^)'";]+)([\\"']*\s*;?)/gi,this.IMPORT_JS_REGEX=/^(import\s*\(['"]+)([^'"]+)(["'])/i,this.no_wombatRe=/WB_wombat_/g,this.srcsetRe=/\s*(\S*\s+[\d.]+[wx]),|(?:\s*,(?:\s+|(?=https?:)))/,this.cookie_path_regex=/\bPath='?"?([^;'"\s]+)/i,this.cookie_domain_regex=/\bDomain=([^;'"\s]+)/i,this.cookie_expires_regex=/\bExpires=([^;'"]+)/gi,this.SetCookieRe=/,(?![|])/,this.IP_RX=/^(\d)+\.(\d)+\.(\d)+\.(\d)+$/,this.FullHTMLRegex=/^\s*<(?:html|head|body|!doctype html)/i,this.IsTagRegex=/^\s*=0){var fnMapping=this._map.splice(idx,1);return fnMapping[0][1]}return null},FuncMap.prototype.map=function(param){for(var i=0;i0&&afw.preserveMedia(media)})},AutoFetcher.prototype.terminate=function(){this.worker.terminate()},AutoFetcher.prototype.justFetch=function(urls){this.worker.postMessage({type:"fetch-all",values:urls})},AutoFetcher.prototype.fetchAsPage=function(url,originalUrl,title){if(url){var headers={"X-Wombat-History-Page":originalUrl};if(title){var encodedTitle=encodeURIComponent(title.trim());title&&(headers["X-Wombat-History-Title"]=encodedTitle)}var fetchData={url:url,options:{headers:headers,cache:"no-store"}};this.justFetch([fetchData])}},AutoFetcher.prototype.postMessage=function(msg,deferred){if(deferred){var afWorker=this;return void Promise.resolve().then(function(){afWorker.worker.postMessage(msg)})}this.worker.postMessage(msg)},AutoFetcher.prototype.preserveSrcset=function(srcset,mod){this.postMessage({type:"values",srcset:{value:srcset,mod:mod,presplit:true}},true)},AutoFetcher.prototype.preserveDataSrcset=function(elem){this.postMessage({type:"values",srcset:{value:elem.dataset.srcset,mod:this.rwMod(elem),presplit:false}},true)},AutoFetcher.prototype.preserveMedia=function(media){this.postMessage({type:"values",media:media},true)},AutoFetcher.prototype.getSrcset=function(elem){return this.wombat.wb_getAttribute?this.wombat.wb_getAttribute.call(elem,"srcset"):elem.getAttribute("srcset")},AutoFetcher.prototype.rwMod=function(elem){switch(elem.tagName){case"SOURCE":return elem.parentElement&&elem.parentElement.tagName==="PICTURE"?"im_":"oe_";case"IMG":return"im_";}return"oe_"},AutoFetcher.prototype.extractFromLocalDoc=function(){var afw=this;Promise.resolve().then(function(){for(var msg={type:"values",context:{docBaseURI:document.baseURI}},media=[],i=0,sheets=document.styleSheets;i=0||scriptType.indexOf("ecmascript")>=0)&&(!!(scriptType.indexOf("json")>=0)||!!(scriptType.indexOf("text/")>=0))},Wombat.prototype.skipWrapScriptTextBasedOnText=function(text){if(!text||text.indexOf(this.WB_ASSIGN_FUNC)>=0||text.indexOf("<")===0)return true;for(var override_props=["window","self","document","location","top","parent","frames","opener"],i=0;i=0)return false;return true},Wombat.prototype.nodeHasChildren=function(node){if(!node)return false;if(typeof node.hasChildNodes==="function")return node.hasChildNodes();var kids=node.children||node.childNodes;return!!kids&&kids.length>0},Wombat.prototype.rwModForElement=function(elem,attrName){if(!elem)return undefined;var mod="mp_";if(!(elem.tagName==="LINK"&&attrName==="href")){var maybeMod=this.tagToMod[elem.tagName];maybeMod!=null&&(mod=maybeMod[attrName])}else if(elem.rel){var relV=elem.rel.trim().toLowerCase(),asV=this.wb_getAttribute.call(elem,"as");if(asV&&this.linkTagMods.linkRelToAs[relV]!=null){var asMods=this.linkTagMods.linkRelToAs[relV];mod=asMods[asV.toLowerCase()]}else this.linkTagMods[relV]!=null&&(mod=this.linkTagMods[relV])}return mod},Wombat.prototype.removeWBOSRC=function(elem){elem.tagName!=="SCRIPT"||elem.__$removedWBOSRC$__||(elem.hasAttribute("__wb_orig_src")&&elem.removeAttribute("__wb_orig_src"),elem.__$removedWBOSRC$__=true)},Wombat.prototype.retrieveWBOSRC=function(elem){if(elem.tagName==="SCRIPT"&&!elem.__$removedWBOSRC$__){var maybeWBOSRC;return maybeWBOSRC=this.wb_getAttribute?this.wb_getAttribute.call(elem,"__wb_orig_src"):elem.getAttribute("__wb_orig_src"),maybeWBOSRC==null&&(elem.__$removedWBOSRC$__=true),maybeWBOSRC}return undefined},Wombat.prototype.wrapScriptTextJsProxy=function(scriptText){return"var _____WB$wombat$assign$function_____ = function(name) {return (self._wb_wombat && self._wb_wombat.local_init && self._wb_wombat.local_init(name)) || self[name]; };\nif (!self.__WB_pmw) { self.__WB_pmw = function(obj) { this.__WB_source = obj; return this; } }\n{\nlet window = _____WB$wombat$assign$function_____(\"window\");\nlet globalThis = _____WB$wombat$assign$function_____(\"globalThis\");\nlet self = _____WB$wombat$assign$function_____(\"self\");\nlet document = _____WB$wombat$assign$function_____(\"document\");\nlet location = _____WB$wombat$assign$function_____(\"location\");\nlet top = _____WB$wombat$assign$function_____(\"top\");\nlet parent = _____WB$wombat$assign$function_____(\"parent\");\nlet frames = _____WB$wombat$assign$function_____(\"frames\");\nlet opener = _____WB$wombat$assign$function_____(\"opener\");\n{\n"+scriptText.replace(this.DotPostMessageRe,".__WB_pmw(self.window)$1")+"\n\n}}"},Wombat.prototype.watchElem=function(elem,func){if(!this.$wbwindow.MutationObserver)return false;var m=new this.$wbwindow.MutationObserver(function(records,observer){for(var r,i=0;i"},Wombat.prototype.getFinalUrl=function(useRel,mod,url){var prefix=useRel?this.wb_rel_prefix:this.wb_abs_prefix;return mod==null&&(mod=this.wb_info.mod),this.wb_info.is_live||(prefix+=this.wb_info.wombat_ts),prefix+=mod,prefix[prefix.length-1]!=="/"&&(prefix+="/"),prefix+url},Wombat.prototype.resolveRelUrl=function(url,doc){var docObj=doc||this.$wbwindow.document,parser=this.makeParser(docObj.baseURI,docObj),hash=parser.href.lastIndexOf("#"),href=hash>=0?parser.href.substring(0,hash):parser.href,lastslash=href.lastIndexOf("/");return parser.href=lastslash>=0&&lastslash!==href.length-1?href.substring(0,lastslash+1)+url:href+url,parser.href},Wombat.prototype.extractOriginalURL=function(rewrittenUrl){if(!rewrittenUrl)return"";if(this.wb_is_proxy)return rewrittenUrl;var rwURLString=rewrittenUrl.toString(),url=rwURLString;if(this.startsWithOneOf(url,this.IGNORE_PREFIXES))return url;if(url.startsWith(this.wb_info.static_prefix))return url;var start;start=this.startsWith(url,this.wb_abs_prefix)?this.wb_abs_prefix.length:this.wb_rel_prefix&&this.startsWith(url,this.wb_rel_prefix)?this.wb_rel_prefix.length:this.wb_rel_prefix?1:0;var index=url.indexOf("/http",start);return index<0&&(index=url.indexOf("///",start)),index<0&&(index=url.indexOf("/blob:",start)),index<0&&(index=url.indexOf("/about:blank",start)),index>=0?url=url.substr(index+1):(index=url.indexOf(this.wb_replay_prefix),index>=0&&(url=url.substr(index+this.wb_replay_prefix.length)),url.length>4&&url.charAt(2)==="_"&&url.charAt(3)==="/"&&(url=url.substr(4)),url!==rwURLString&&!this.startsWithOneOf(url,this.VALID_PREFIXES)&&!this.startsWith(url,"blob:")&&(url=this.wb_orig_scheme+url)),rwURLString.charAt(0)==="/"&&rwURLString.charAt(1)!=="/"&&this.startsWith(url,this.wb_orig_origin)&&(url=url.substr(this.wb_orig_origin.length)),this.startsWith(url,this.REL_PREFIX)?this.wb_info.wombat_scheme+":"+url:url},Wombat.prototype.makeParser=function(maybeRewrittenURL,doc){var originalURL=this.extractOriginalURL(maybeRewrittenURL),docElem=doc;return doc||(this.$wbwindow.location.href==="about:blank"&&this.$wbwindow.opener?docElem=this.$wbwindow.opener.document:docElem=this.$wbwindow.document),this._makeURLParser(originalURL,docElem)},Wombat.prototype._makeURLParser=function(url,docElem){try{return new this.$wbwindow.URL(url,docElem.baseURI)}catch(e){}var p=docElem.createElement("a");return p._no_rewrite=true,p.href=url,p},Wombat.prototype.defProp=function(obj,prop,setFunc,getFunc,enumerable){var existingDescriptor=Object.getOwnPropertyDescriptor(obj,prop);if(existingDescriptor&&!existingDescriptor.configurable)return false;if(!getFunc)return false;var descriptor={configurable:true,enumerable:enumerable||false,get:getFunc};setFunc&&(descriptor.set=setFunc);try{return Object.defineProperty(obj,prop,descriptor),true}catch(e){return console.warn("Failed to redefine property %s",prop,e.message),false}},Wombat.prototype.defGetterProp=function(obj,prop,getFunc,enumerable){var existingDescriptor=Object.getOwnPropertyDescriptor(obj,prop);if(existingDescriptor&&!existingDescriptor.configurable)return false;if(!getFunc)return false;try{return Object.defineProperty(obj,prop,{configurable:true,enumerable:enumerable||false,get:getFunc}),true}catch(e){return console.warn("Failed to redefine property %s",prop,e.message),false}},Wombat.prototype.getOrigGetter=function(obj,prop){var orig_getter;if(obj.__lookupGetter__&&(orig_getter=obj.__lookupGetter__(prop)),!orig_getter&&Object.getOwnPropertyDescriptor){var props=Object.getOwnPropertyDescriptor(obj,prop);props&&(orig_getter=props.get)}return orig_getter},Wombat.prototype.getOrigSetter=function(obj,prop){var orig_setter;if(obj.__lookupSetter__&&(orig_setter=obj.__lookupSetter__(prop)),!orig_setter&&Object.getOwnPropertyDescriptor){var props=Object.getOwnPropertyDescriptor(obj,prop);props&&(orig_setter=props.set)}return orig_setter},Wombat.prototype.getAllOwnProps=function(obj){for(var ownProps=[],props=Object.getOwnPropertyNames(obj),i=0;i "+final_href),actualLocation.href=final_href}}},Wombat.prototype.checkLocationChange=function(wombatLoc,isTop){var locType=typeof wombatLoc,actual_location=isTop?this.$wbwindow.__WB_replay_top.location:this.$wbwindow.location;locType==="string"?this.updateLocation(wombatLoc,actual_location.href,actual_location):locType==="object"&&this.updateLocation(wombatLoc.href,wombatLoc._orig_href,actual_location)},Wombat.prototype.checkAllLocations=function(){return!this.wb_wombat_updating&&void(this.wb_wombat_updating=true,this.checkLocationChange(this.$wbwindow.WB_wombat_location,false),this.$wbwindow.WB_wombat_location!=this.$wbwindow.__WB_replay_top.WB_wombat_location&&this.checkLocationChange(this.$wbwindow.__WB_replay_top.WB_wombat_location,true),this.wb_wombat_updating=false)},Wombat.prototype.proxyToObj=function(source){if(source)try{var proxyRealObj=source.__WBProxyRealObj__;if(proxyRealObj)return proxyRealObj}catch(e){}return source},Wombat.prototype.objToProxy=function(obj){if(obj)try{var maybeWbProxy=obj._WB_wombat_obj_proxy;if(maybeWbProxy)return maybeWbProxy}catch(e){}return obj},Wombat.prototype.defaultProxyGet=function(obj,prop,ownProps,fnCache){switch(prop){case"__WBProxyRealObj__":return obj;case"location":case"WB_wombat_location":return obj.WB_wombat_location;case"_WB_wombat_obj_proxy":return obj._WB_wombat_obj_proxy;case"__WB_pmw":case this.WB_ASSIGN_FUNC:case this.WB_CHECK_THIS_FUNC:return obj[prop];case"origin":return obj.WB_wombat_location.origin;case"constructor":return obj.constructor;}var retVal=obj[prop],type=typeof retVal;if(type==="function"&&ownProps.indexOf(prop)!==-1){switch(prop){case"requestAnimationFrame":case"cancelAnimationFrame":{if(!this.isNativeFunction(retVal))return retVal;break}case"eval":if(this.isNativeFunction(retVal))return this.wrappedEval(retVal);}var cachedFN=fnCache[prop];return cachedFN&&cachedFN.original===retVal||(cachedFN={original:retVal,boundFn:retVal.bind(obj)},fnCache[prop]=cachedFN),cachedFN.boundFn}return type==="object"&&retVal&&retVal._WB_wombat_obj_proxy?(retVal instanceof this.WBWindow&&this.initNewWindowWombat(retVal),retVal._WB_wombat_obj_proxy):retVal},Wombat.prototype.setLoc=function(loc,originalURL){var parser=this.makeParser(originalURL,loc.ownerDocument);loc._orig_href=originalURL,loc._parser=parser;var href=parser.href;loc._hash=parser.hash,loc._href=href,loc._host=parser.host,loc._hostname=parser.hostname,loc._origin=parser.origin?parser.host?parser.origin:"null":parser.protocol+"//"+parser.hostname+(parser.port?":"+parser.port:""),loc._pathname=parser.pathname,loc._port=parser.port,loc._protocol=parser.protocol,loc._search=parser.search,Object.defineProperty||(loc.href=href,loc.hash=parser.hash,loc.host=loc._host,loc.hostname=loc._hostname,loc.origin=loc._origin,loc.pathname=loc._pathname,loc.port=loc._port,loc.protocol=loc._protocol,loc.search=loc._search)},Wombat.prototype.makeGetLocProp=function(prop,origGetter){var wombat=this;return function newGetLocProp(){if(this._no_rewrite)return origGetter.call(this,prop);var curr_orig_href=origGetter.call(this,"href");return prop==="href"?wombat.extractOriginalURL(curr_orig_href):prop==="ancestorOrigins"?[]:(this._orig_href!==curr_orig_href&&wombat.setLoc(this,curr_orig_href),this["_"+prop])}},Wombat.prototype.makeSetLocProp=function(prop,origSetter,origGetter){var wombat=this;return function newSetLocProp(value){if(this._no_rewrite)return origSetter.call(this,prop,value);if(this["_"+prop]!==value){if(this["_"+prop]=value,!this._parser){var href=origGetter.call(this);this._parser=wombat.makeParser(href,this.ownerDocument)}var rel=false;if(prop==="href"&&typeof value==="string")if(value&&this._parser instanceof URL)try{value=new URL(value,this._parser).href}catch(e){console.warn("Error resolving URL",e)}else value&&(value[0]==="."||value[0]==="#"?value=wombat.resolveRelUrl(value,this.ownerDocument):value[0]==="/"&&(value.length>1&&value[1]==="/"?value=this._parser.protocol+value:(rel=true,value=WB_wombat_location.origin+value)));try{this._parser[prop]=value}catch(e){console.log("Error setting "+prop+" = "+value)}prop==="hash"?(value=this._parser[prop],origSetter.call(this,"hash",value)):(rel=rel||value===this._parser.pathname,value=wombat.rewriteUrl(this._parser.href,rel),origSetter.call(this,"href",value))}}},Wombat.prototype.styleReplacer=function(match,n1,n2,n3,offset,string){return n1+this.rewriteUrl(n2)+n3},Wombat.prototype.domConstructorErrorChecker=function(thisObj,what,args,numRequiredArgs){var errorMsg,needArgs=typeof numRequiredArgs==="number"?numRequiredArgs:1;if(thisObj instanceof this.WBWindow?errorMsg="Failed to construct '"+what+"': Please use the 'new' operator, this DOM object constructor cannot be called as a function.":args&&args.length=0)return url;if(url.indexOf(this.wb_rel_prefix)===0&&url.indexOf("http")>1){var scheme_sep=url.indexOf(":/");return scheme_sep>0&&url[scheme_sep+2]!=="/"?url.substring(0,scheme_sep+2)+"/"+url.substring(scheme_sep+2):url}return this.getFinalUrl(true,mod,this.wb_orig_origin+url)}url.charAt(0)==="."&&(url=this.resolveRelUrl(url,doc));var prefix=this.startsWithOneOf(url.toLowerCase(),this.VALID_PREFIXES);if(prefix){var orig_host=this.replayTopHost,orig_protocol=this.replayTopProtocol,prefix_host=prefix+orig_host+"/";if(this.startsWith(url,prefix_host)){if(this.startsWith(url,this.wb_replay_prefix))return url;var curr_scheme=orig_protocol+"//",path=url.substring(prefix_host.length),rebuild=false;return path.indexOf(this.wb_rel_prefix)<0&&url.indexOf("/static/")<0&&(path=this.getFinalUrl(true,mod,WB_wombat_location.origin+"/"+path),rebuild=true),prefix!==curr_scheme&&prefix!==this.REL_PREFIX&&(rebuild=true),rebuild&&(url=useRel?"":curr_scheme+orig_host,path&&path[0]!=="/"&&(url+="/"),url+=path),url}return this.getFinalUrl(useRel,mod,url)}return prefix=this.startsWithOneOf(url,this.BAD_PREFIXES),prefix?this.getFinalUrl(useRel,mod,this.extractOriginalURL(url)):url},Wombat.prototype.rewriteUrl=function(url,useRel,mod,doc){var rewritten=this.rewriteUrl_(url,useRel,mod,doc);return this.debug_rw&&(url===rewritten?console.log("NOT REWRITTEN "+url):console.log("REWRITE: "+url+" -> "+rewritten)),rewritten},Wombat.prototype.performAttributeRewrite=function(elem,name,value,absUrlOnly){switch(name){case"innerHTML":case"outerHTML":return this.rewriteHtml(value);case"filter":return this.rewriteInlineStyle(value);case"style":return this.rewriteStyle(value);case"srcset":return this.rewriteSrcset(value,elem);}if(absUrlOnly&&!this.startsWithOneOf(value,this.VALID_PREFIXES))return value;var mod=this.rwModForElement(elem,name);return this.wbUseAFWorker&&this.WBAutoFetchWorker&&this.isSavedDataSrcSrcset(elem)&&this.WBAutoFetchWorker.preserveDataSrcset(elem),this.rewriteUrl(value,false,mod,elem.ownerDocument)},Wombat.prototype.rewriteAttr=function(elem,name,absUrlOnly){var changed=false;if(!elem||!elem.getAttribute||elem._no_rewrite||elem["_"+name])return changed;var value=this.wb_getAttribute.call(elem,name);if(!value||this.startsWith(value,"javascript:"))return changed;var new_value=this.performAttributeRewrite(elem,name,value,absUrlOnly);return new_value!==value&&(this.removeWBOSRC(elem),this.wb_setAttribute.call(elem,name,new_value),changed=true),changed},Wombat.prototype.noExceptRewriteStyle=function(style){try{return this.rewriteStyle(style)}catch(e){return style}},Wombat.prototype.rewriteStyle=function(style){if(!style)return style;var value=style;return typeof style==="object"&&(value=style.toString()),typeof value==="string"?value.replace(this.STYLE_REGEX,this.styleReplacer).replace(this.IMPORT_REGEX,this.styleReplacer).replace(this.no_wombatRe,""):value},Wombat.prototype.rewriteSrcset=function(value,elem){if(!value)return"";for(var v,split=value.split(this.srcsetRe),values=[],mod=this.rwModForElement(elem,"srcset"),i=0;i=0){var JS="javascript:";new_value="javascript:window.parent._wb_wombat.initNewWindowWombat(window);"+value.substr(11)}return new_value||(new_value=this.rewriteUrl(value,false,this.rwModForElement(elem,attrName))),new_value!==value&&(this.wb_setAttribute.call(elem,attrName,new_value),true)},Wombat.prototype.rewriteScript=function(elem){if(elem.hasAttribute("src")||!elem.textContent||!this.$wbwindow.Proxy)return this.rewriteAttr(elem,"src");if(this.skipWrapScriptBasedOnType(elem.type))return false;var text=elem.textContent.trim();return!this.skipWrapScriptTextBasedOnText(text)&&(elem.textContent=this.wrapScriptTextJsProxy(text),true)},Wombat.prototype.rewriteSVGElem=function(elem){var changed=this.rewriteAttr(elem,"filter");return changed=this.rewriteAttr(elem,"style")||changed,changed=this.rewriteAttr(elem,"xlink:href")||changed,changed=this.rewriteAttr(elem,"href")||changed,changed=this.rewriteAttr(elem,"src")||changed,changed},Wombat.prototype.rewriteElem=function(elem){var changed=false;if(!elem)return changed;if(elem instanceof SVGElement)changed=this.rewriteSVGElem(elem);else switch(elem.tagName){case"META":var maybeCSP=this.wb_getAttribute.call(elem,"http-equiv");maybeCSP&&maybeCSP.toLowerCase()==="content-security-policy"&&(this.wb_setAttribute.call(elem,"http-equiv","_"+maybeCSP),changed=true);break;case"STYLE":var new_content=this.rewriteStyle(elem.textContent);elem.textContent!==new_content&&(elem.textContent=new_content,changed=true,this.wbUseAFWorker&&this.WBAutoFetchWorker&&elem.sheet!=null&&this.WBAutoFetchWorker.deferredSheetExtraction(elem.sheet));break;case"LINK":changed=this.rewriteAttr(elem,"href"),this.wbUseAFWorker&&elem.rel==="stylesheet"&&this._addEventListener(elem,"load",this.utilFns.wbSheetMediaQChecker);break;case"IMG":changed=this.rewriteAttr(elem,"src"),changed=this.rewriteAttr(elem,"srcset")||changed,changed=this.rewriteAttr(elem,"style")||changed,this.wbUseAFWorker&&this.WBAutoFetchWorker&&elem.dataset.srcset&&this.WBAutoFetchWorker.preserveDataSrcset(elem);break;case"OBJECT":if(this.wb_info.isSW&&elem.parentElement&&elem.getAttribute("type")==="application/pdf"){for(var iframe=this.$wbwindow.document.createElement("IFRAME"),i=0;i0;)for(var child,children=rewriteQ.shift(),i=0;i"+rwString+"","text/html");if(!inner_doc||!this.nodeHasChildren(inner_doc.head)||!inner_doc.head.children[0].content)return rwString;var template=inner_doc.head.children[0];if(template._no_rewrite=true,this.recurseRewriteElem(template.content)){var new_html=template.innerHTML;if(checkEndTag){var first_elem=template.content.children&&template.content.children[0];if(first_elem){var end_tag="";this.endsWith(new_html,end_tag)&&!this.endsWith(rwString.toLowerCase(),end_tag)&&(new_html=new_html.substring(0,new_html.length-end_tag.length))}else if(rwString[0]!=="<"||rwString[rwString.length-1]!==">")return this.write_buff+=rwString,undefined}return new_html}return rwString},Wombat.prototype.rewriteHtmlFull=function(string,checkEndTag){var inner_doc=new DOMParser().parseFromString(string,"text/html");if(!inner_doc)return string;for(var changed=false,i=0;i=0)inner_doc.documentElement._no_rewrite=true,new_html=this.reconstructDocType(inner_doc.doctype)+inner_doc.documentElement.outerHTML;else{inner_doc.head._no_rewrite=true,inner_doc.body._no_rewrite=true;var headHasKids=this.nodeHasChildren(inner_doc.head),bodyHasKids=this.nodeHasChildren(inner_doc.body);if(new_html=(headHasKids?inner_doc.head.outerHTML:"")+(bodyHasKids?inner_doc.body.outerHTML:""),checkEndTag)if(inner_doc.all.length>3){var end_tag="";this.endsWith(new_html,end_tag)&&!this.endsWith(string.toLowerCase(),end_tag)&&(new_html=new_html.substring(0,new_html.length-end_tag.length))}else if(string[0]!=="<"||string[string.length-1]!==">")return void(this.write_buff+=string);new_html=this.reconstructDocType(inner_doc.doctype)+new_html}return new_html}return string},Wombat.prototype.rewriteInlineStyle=function(orig){var decoded;try{decoded=decodeURIComponent(orig)}catch(e){decoded=orig}if(decoded!==orig){var parts=this.rewriteStyle(decoded).split(",",2);return parts[0]+","+encodeURIComponent(parts[1])}return this.rewriteStyle(orig)},Wombat.prototype.rewriteCookie=function(cookie){var wombat=this,rwCookie=cookie.replace(this.wb_abs_prefix,"").replace(this.wb_rel_prefix,"");return rwCookie=rwCookie.replace(this.cookie_domain_regex,function(m,m1){var message={domain:m1,cookie:rwCookie,wb_type:"cookie"};return wombat.sendTopMessage(message,true),wombat.$wbwindow.location.hostname.indexOf(".")>=0&&!wombat.IP_RX.test(wombat.$wbwindow.location.hostname)?"Domain=."+wombat.$wbwindow.location.hostname:""}).replace(this.cookie_path_regex,function(m,m1){var rewritten=wombat.rewriteUrl(m1);return rewritten.indexOf(wombat.wb_curr_host)===0&&(rewritten=rewritten.substring(wombat.wb_curr_host.length)),"Path="+rewritten}),wombat.$wbwindow.location.protocol!=="https:"&&(rwCookie=rwCookie.replace("secure","")),rwCookie.replace(",|",",")},Wombat.prototype.rewriteWorker=function(workerUrl){if(!workerUrl)return workerUrl;workerUrl=workerUrl.toString();var isBlob=workerUrl.indexOf("blob:")===0,isJS=workerUrl.indexOf("javascript:")===0;if(!isBlob&&!isJS){if(!this.startsWithOneOf(workerUrl,this.VALID_PREFIXES)&&!this.startsWith(workerUrl,"/")&&!this.startsWithOneOf(workerUrl,this.BAD_PREFIXES)){var rurl=this.resolveRelUrl(workerUrl,this.$wbwindow.document);return this.rewriteUrl(rurl,false,"wkr_",this.$wbwindow.document)}return this.rewriteUrl(workerUrl,false,"wkr_",this.$wbwindow.document)}var workerCode=isJS?workerUrl.replace("javascript:",""):null;if(isBlob){var x=new XMLHttpRequest;this.utilFns.XHRopen.call(x,"GET",workerUrl,false),this.utilFns.XHRsend.call(x),workerCode=x.responseText.replace(this.workerBlobRe,"").replace(this.rmCheckThisInjectRe,"this")}if(this.wb_info.static_prefix||this.wb_info.ww_rw_script){var originalURL=this.$wbwindow.document.baseURI,ww_rw=this.wb_info.ww_rw_script||this.wb_info.static_prefix+"wombatWorkers.js",rw="(function() { self.importScripts('"+ww_rw+"'); new WBWombat({'prefix': '"+this.wb_abs_prefix+"', 'prefixMod': '"+this.wb_abs_prefix+"wkrf_/', 'originalURL': '"+originalURL+"'}); })();";workerCode=rw+workerCode}var blob=new Blob([workerCode],{type:"application/javascript"});return URL.createObjectURL(blob)},Wombat.prototype.rewriteTextNodeFn=function(fnThis,originalFn,argsObj){var args,deproxiedThis=this.proxyToObj(fnThis);if(argsObj.length>0&&deproxiedThis.parentElement&&deproxiedThis.parentElement.tagName==="STYLE"){args=new Array(argsObj.length);var dataIndex=argsObj.length-1;dataIndex===2?(args[0]=argsObj[0],args[1]=argsObj[1]):dataIndex===1&&(args[0]=argsObj[0]),args[dataIndex]=this.rewriteStyle(argsObj[dataIndex])}else args=argsObj;return originalFn.__WB_orig_apply?originalFn.__WB_orig_apply(deproxiedThis,args):originalFn.apply(deproxiedThis,args)},Wombat.prototype.rewriteDocWriteWriteln=function(fnThis,originalFn,argsObj){var string,thisObj=this.proxyToObj(fnThis),argLen=argsObj.length;if(argLen===0)return originalFn.call(thisObj);string=argLen===1?argsObj[0]:Array.prototype.join.call(argsObj,"");var new_buff=this.rewriteHtml(string,true),res=originalFn.call(thisObj,new_buff);return this.initNewWindowWombat(thisObj.defaultView),res},Wombat.prototype.rewriteChildNodeFn=function(fnThis,originalFn,argsObj){var thisObj=this.proxyToObj(fnThis);if(argsObj.length===0)return originalFn.call(thisObj);var newArgs=this.rewriteElementsInArguments(argsObj);return originalFn.__WB_orig_apply?originalFn.__WB_orig_apply(thisObj,newArgs):originalFn.apply(thisObj,newArgs)},Wombat.prototype.rewriteInsertAdjHTMLOrElemArgs=function(fnThis,originalFn,position,textOrElem,rwHTML){var fnThisObj=this.proxyToObj(fnThis);return fnThisObj._no_rewrite?originalFn.call(fnThisObj,position,textOrElem):rwHTML?originalFn.call(fnThisObj,position,this.rewriteHtml(textOrElem)):(this.rewriteElemComplete(textOrElem),originalFn.call(fnThisObj,position,textOrElem))},Wombat.prototype.rewriteSetTimeoutInterval=function(fnThis,originalFn,argsObj){var rw=this.isString(argsObj[0]),args=rw?new Array(argsObj.length):argsObj;if(rw){args[0]=this.$wbwindow.Proxy?this.wrapScriptTextJsProxy(argsObj[0]):argsObj[0].replace(/\blocation\b/g,"WB_wombat_$&");for(var i=1;i0&&cssStyleValueOverride(this.$wbwindow.CSSStyleValue,"parse"),this.$wbwindow.CSSStyleValue.parseAll&&this.$wbwindow.CSSStyleValue.parseAll.toString().indexOf("[native code]")>0&&cssStyleValueOverride(this.$wbwindow.CSSStyleValue,"parseAll")}if(this.$wbwindow.CSSKeywordValue&&this.$wbwindow.CSSKeywordValue.prototype){var oCSSKV=this.$wbwindow.CSSKeywordValue;this.$wbwindow.CSSKeywordValue=function(CSSKeywordValue_){return function CSSKeywordValue(cssValue){return wombat.domConstructorErrorChecker(this,"CSSKeywordValue",arguments),new CSSKeywordValue_(wombat.rewriteStyle(cssValue))}}(this.$wbwindow.CSSKeywordValue),this.$wbwindow.CSSKeywordValue.prototype=oCSSKV.prototype,Object.defineProperty(this.$wbwindow.CSSKeywordValue.prototype,"constructor",{value:this.$wbwindow.CSSKeywordValue}),addToStringTagToClass(this.$wbwindow.CSSKeywordValue,"CSSKeywordValue")}if(this.$wbwindow.StylePropertyMap&&this.$wbwindow.StylePropertyMap.prototype){var originalSet=this.$wbwindow.StylePropertyMap.prototype.set;this.$wbwindow.StylePropertyMap.prototype.set=function set(){if(arguments.length<=1)return originalSet.__WB_orig_apply?originalSet.__WB_orig_apply(this,arguments):originalSet.apply(this,arguments);var newArgs=new Array(arguments.length);newArgs[0]=arguments[0];for(var i=1;i")&&(array[0]=wombat.rewriteHtml(array[0]),options.type="text/html"),new Blob_(array,options)}}(this.$wbwindow.Blob),this.$wbwindow.Blob.prototype=orig_blob.prototype}},Wombat.prototype.initWSOverride=function(){this.$wbwindow.WebSocket&&this.$wbwindow.WebSocket.prototype&&(this.$wbwindow.WebSocket=function(WebSocket_){function WebSocket(url,protocols){this.addEventListener=function(){},this.removeEventListener=function(){},this.close=function(){},this.send=function(data){console.log("ws send",data)},this.protocol=protocols&&protocols.length?protocols[0]:"",this.url=url,this.readyState=0}return WebSocket.CONNECTING=0,WebSocket.OPEN=1,WebSocket.CLOSING=2,WebSocket.CLOSED=3,WebSocket}(this.$wbwindow.WebSocket),Object.defineProperty(this.$wbwindow.WebSocket.prototype,"constructor",{value:this.$wbwindow.WebSocket}),addToStringTagToClass(this.$wbwindow.WebSocket,"WebSocket"))},Wombat.prototype.initDocTitleOverride=function(){var orig_get_title=this.getOrigGetter(this.$wbwindow.document,"title"),orig_set_title=this.getOrigSetter(this.$wbwindow.document,"title"),wombat=this,set_title=function title(value){var res=orig_set_title.call(this,value),message={wb_type:"title",title:value};return wombat.sendTopMessage(message),res};this.defProp(this.$wbwindow.document,"title",set_title,orig_get_title)},Wombat.prototype.initFontFaceOverride=function(){if(this.$wbwindow.FontFace){var wombat=this,origFontFace=this.$wbwindow.FontFace;this.$wbwindow.FontFace=function(FontFace_){return function FontFace(family,source,descriptors){wombat.domConstructorErrorChecker(this,"FontFace",arguments,2);var rwSource=source;return source!=null&&(typeof source==="string"?rwSource=wombat.rewriteInlineStyle(source):rwSource=wombat.rewriteInlineStyle(source.toString())),new FontFace_(family,rwSource,descriptors)}}(this.$wbwindow.FontFace),this.$wbwindow.FontFace.prototype=origFontFace.prototype,Object.defineProperty(this.$wbwindow.FontFace.prototype,"constructor",{value:this.$wbwindow.FontFace}),addToStringTagToClass(this.$wbwindow.FontFace,"FontFace")}},Wombat.prototype.initFixedRatio=function(value){try{this.$wbwindow.devicePixelRatio=value}catch(e){}if(Object.defineProperty)try{Object.defineProperty(this.$wbwindow,"devicePixelRatio",{value:value,writable:false})}catch(e){}},Wombat.prototype.initPaths=function(wbinfo){wbinfo.wombat_opts=wbinfo.wombat_opts||{},Object.assign(this.wb_info,wbinfo),this.wb_opts=wbinfo.wombat_opts,this.wb_replay_prefix=wbinfo.prefix,this.wb_is_proxy=wbinfo.proxy_magic||!this.wb_replay_prefix,this.wb_info.top_host=this.wb_info.top_host||"*",this.wb_curr_host=this.$wbwindow.location.protocol+"//"+this.$wbwindow.location.host,this.wb_info.wombat_opts=this.wb_info.wombat_opts||{},this.wb_orig_scheme=wbinfo.wombat_scheme+"://",this.wb_orig_origin=this.wb_orig_scheme+wbinfo.wombat_host,this.wb_abs_prefix=this.wb_replay_prefix,this.wb_capture_date_part=!wbinfo.is_live&&wbinfo.wombat_ts?"/"+wbinfo.wombat_ts+"/":"",this.initBadPrefixes(this.wb_replay_prefix),this.initCookiePreset()},Wombat.prototype.initSeededRandom=function(seed){this.$wbwindow.Math.seed=parseInt(seed);var wombat=this;this.$wbwindow.Math.random=function random(){return wombat.$wbwindow.Math.seed=(wombat.$wbwindow.Math.seed*9301+49297)%233280,wombat.$wbwindow.Math.seed/233280}},Wombat.prototype.initHistoryOverrides=function(){this.overrideHistoryFunc("pushState"),this.overrideHistoryFunc("replaceState");var wombat=this;this.$wbwindow.addEventListener("popstate",function(event){wombat.sendHistoryUpdate(wombat.$wbwindow.WB_wombat_location.href,wombat.$wbwindow.document.title)})},Wombat.prototype.initCookiePreset=function(){if(this.wb_info.presetCookie)for(var splitCookies=this.wb_info.presetCookie.split(";"),i=0;i2&&!this.__WB_xhr_open_arguments[2]&&navigator.userAgent.indexOf("Firefox")===-1&&(this.__WB_xhr_open_arguments[2]=true,console.warn("wombat.js: Sync XHR not supported in SW-based replay in this browser, converted to async")),this._no_rewrite||(this.__WB_xhr_open_arguments[1]=wombat.rewriteUrl(this.__WB_xhr_open_arguments[1])),origOpen.apply(this,this.__WB_xhr_open_arguments),!wombat.startsWith(this.__WB_xhr_open_arguments[1],"data:")){for(const[name,value]of this.__WB_xhr_headers.entries())origSetRequestHeader.call(this,name,value);origSetRequestHeader.call(this,"X-Pywb-Requested-With","XMLHttpRequest")}return origSend.call(this,value)}}else if(this.$wbwindow.XMLHttpRequest.prototype.open){var origXMLHttpOpen=this.$wbwindow.XMLHttpRequest.prototype.open;this.utilFns.XHRopen=origXMLHttpOpen,this.utilFns.XHRsend=this.$wbwindow.XMLHttpRequest.prototype.send,this.$wbwindow.XMLHttpRequest.prototype.open=function open(method,url,async,user,password){var rwURL=this._no_rewrite?url:wombat.rewriteUrl(url),openAsync=true;async==null||async||(openAsync=false),origXMLHttpOpen.call(this,method,rwURL,openAsync,user,password),wombat.startsWith(rwURL,"data:")||this.setRequestHeader("X-Pywb-Requested-With","XMLHttpRequest")}}if(this.$wbwindow.fetch){var orig_fetch=this.$wbwindow.fetch;this.$wbwindow.fetch=function fetch(input,init_opts){var rwInput=input,inputType=typeof input;if(inputType==="string")rwInput=wombat.rewriteUrl(input);else if(inputType==="object"&&input.url){var new_url=wombat.rewriteUrl(input.url);new_url!==input.url&&(rwInput=new Request(new_url,init_opts))}else inputType==="object"&&input.href&&(rwInput=wombat.rewriteUrl(input.href));if(init_opts||(init_opts={}),init_opts.credentials===undefined)try{init_opts.credentials="include"}catch(e){}return orig_fetch.call(wombat.proxyToObj(this),rwInput,init_opts)}}if(this.$wbwindow.Request&&this.$wbwindow.Request.prototype){var orig_request=this.$wbwindow.Request;this.$wbwindow.Request=function(Request_){return function Request(input,init_opts){wombat.domConstructorErrorChecker(this,"Request",arguments);var newInitOpts=init_opts||{},newInput=input,inputType=typeof input;switch(inputType){case"string":newInput=wombat.rewriteUrl(input);break;case"object":if(newInput=input,input.url){var new_url=wombat.rewriteUrl(input.url);new_url!==input.url&&(newInput=new Request_(new_url,input))}else input.href&&(newInput=wombat.rewriteUrl(input.toString(),true));}return newInitOpts.credentials="include",new Request_(newInput,newInitOpts)}}(this.$wbwindow.Request),this.$wbwindow.Request.prototype=orig_request.prototype,Object.defineProperty(this.$wbwindow.Request.prototype,"constructor",{value:this.$wbwindow.Request})}if(this.$wbwindow.Response&&this.$wbwindow.Response.prototype){var originalRedirect=this.$wbwindow.Response.prototype.redirect;this.$wbwindow.Response.prototype.redirect=function redirect(url,status){var rwURL=wombat.rewriteUrl(url,true,null,wombat.$wbwindow.document);return originalRedirect.call(this,rwURL,status)}}if(this.$wbwindow.EventSource&&this.$wbwindow.EventSource.prototype){var origEventSource=this.$wbwindow.EventSource;this.$wbwindow.EventSource=function(EventSource_){return function EventSource(url,configuration){wombat.domConstructorErrorChecker(this,"EventSource",arguments);var rwURL=url;return url!=null&&(rwURL=wombat.rewriteUrl(url)),new EventSource_(rwURL,configuration)}}(this.$wbwindow.EventSource),this.$wbwindow.EventSource.prototype=origEventSource.prototype,Object.defineProperty(this.$wbwindow.EventSource.prototype,"constructor",{value:this.$wbwindow.EventSource}),addToStringTagToClass(this.$wbwindow.EventSource,"EventSource")}},Wombat.prototype.initElementGetSetAttributeOverride=function(){if(!this.wb_opts.skip_setAttribute&&this.$wbwindow.Element&&this.$wbwindow.Element.prototype){var wombat=this,ElementProto=this.$wbwindow.Element.prototype;if(ElementProto.setAttribute){var orig_setAttribute=ElementProto.setAttribute;ElementProto._orig_setAttribute=orig_setAttribute,ElementProto.setAttribute=function setAttribute(name,value){var rwValue=value;if(name&&typeof rwValue==="string"){var lowername=name.toLowerCase();if(this.tagName==="LINK"&&lowername==="href"&&rwValue.indexOf("data:text/css")===0)rwValue=wombat.rewriteInlineStyle(value);else if(lowername==="style")rwValue=wombat.rewriteStyle(value);else if(lowername==="srcset"||lowername==="imagesrcset"&&this.tagName==="LINK")rwValue=wombat.rewriteSrcset(value,this);else{var shouldRW=wombat.shouldRewriteAttr(this.tagName,lowername);shouldRW&&(wombat.removeWBOSRC(this),!this._no_rewrite&&(rwValue=wombat.rewriteUrl(value,false,wombat.rwModForElement(this,lowername))))}}return orig_setAttribute.call(this,name,rwValue)}}if(ElementProto.getAttribute){var orig_getAttribute=ElementProto.getAttribute;this.wb_getAttribute=orig_getAttribute,ElementProto.getAttribute=function getAttribute(name){var result=orig_getAttribute.call(this,name);if(result===null)return result;var lowerName=name;if(name&&(lowerName=name.toLowerCase()),wombat.shouldRewriteAttr(this.tagName,lowerName)){var maybeWBOSRC=wombat.retrieveWBOSRC(this);return maybeWBOSRC?maybeWBOSRC:wombat.extractOriginalURL(result)}return wombat.startsWith(lowerName,"data-")&&wombat.startsWithOneOf(result,wombat.wb_prefixes)?wombat.extractOriginalURL(result):result}}}},Wombat.prototype.initSvgImageOverrides=function(){if(this.$wbwindow.SVGImageElement){var svgImgProto=this.$wbwindow.SVGImageElement.prototype,orig_getAttr=svgImgProto.getAttribute,orig_getAttrNS=svgImgProto.getAttributeNS,orig_setAttr=svgImgProto.setAttribute,orig_setAttrNS=svgImgProto.setAttributeNS,wombat=this;svgImgProto.getAttribute=function getAttribute(name){var value=orig_getAttr.call(this,name);return name.indexOf("xlink:href")>=0||name==="href"?wombat.extractOriginalURL(value):value},svgImgProto.getAttributeNS=function getAttributeNS(ns,name){var value=orig_getAttrNS.call(this,ns,name);return name.indexOf("xlink:href")>=0||name==="href"?wombat.extractOriginalURL(value):value},svgImgProto.setAttribute=function setAttribute(name,value){var rwValue=value;return(name.indexOf("xlink:href")>=0||name==="href")&&(rwValue=wombat.rewriteUrl(value)),orig_setAttr.call(this,name,rwValue)},svgImgProto.setAttributeNS=function setAttributeNS(ns,name,value){var rwValue=value;return(name.indexOf("xlink:href")>=0||name==="href")&&(rwValue=wombat.rewriteUrl(value)),orig_setAttrNS.call(this,ns,name,rwValue)}}},Wombat.prototype.initCreateElementNSFix=function(){if(this.$wbwindow.document.createElementNS&&this.$wbwindow.Document.prototype.createElementNS){var orig_createElementNS=this.$wbwindow.document.createElementNS,wombat=this,createElementNS=function createElementNS(namespaceURI,qualifiedName){return orig_createElementNS.call(wombat.proxyToObj(this),wombat.extractOriginalURL(namespaceURI),qualifiedName)};this.$wbwindow.Document.prototype.createElementNS=createElementNS,this.$wbwindow.document.createElementNS=createElementNS}},Wombat.prototype.initInsertAdjacentElementHTMLOverrides=function(){var Element=this.$wbwindow.Element;if(Element&&Element.prototype){var elementProto=Element.prototype,rewriteFn=this.rewriteInsertAdjHTMLOrElemArgs;if(elementProto.insertAdjacentHTML){var origInsertAdjacentHTML=elementProto.insertAdjacentHTML;elementProto.insertAdjacentHTML=function insertAdjacentHTML(position,text){return rewriteFn(this,origInsertAdjacentHTML,position,text,true)}}if(elementProto.insertAdjacentElement){var origIAdjElem=elementProto.insertAdjacentElement;elementProto.insertAdjacentElement=function insertAdjacentElement(position,element){return rewriteFn(this,origIAdjElem,position,element,false)}}}},Wombat.prototype.initDomOverride=function(){var Node=this.$wbwindow.Node;if(Node&&Node.prototype){var rewriteFn=this.rewriteNodeFuncArgs;if(Node.prototype.appendChild){var originalAppendChild=Node.prototype.appendChild;Node.prototype.appendChild=function appendChild(newNode,oldNode){return rewriteFn(this,originalAppendChild,newNode,oldNode)}}if(Node.prototype.insertBefore){var originalInsertBefore=Node.prototype.insertBefore;Node.prototype.insertBefore=function insertBefore(newNode,oldNode){return rewriteFn(this,originalInsertBefore,newNode,oldNode)}}if(Node.prototype.replaceChild){var originalReplaceChild=Node.prototype.replaceChild;Node.prototype.replaceChild=function replaceChild(newNode,oldNode){return rewriteFn(this,originalReplaceChild,newNode,oldNode)}}this.overridePropToProxy(Node.prototype,"ownerDocument"),this.overridePropToProxy(this.$wbwindow.HTMLHtmlElement.prototype,"parentNode"),this.overridePropToProxy(this.$wbwindow.Event.prototype,"target")}this.$wbwindow.Element&&this.$wbwindow.Element.prototype&&(this.overrideParentNodeAppendPrepend(this.$wbwindow.Element),this.overrideChildNodeInterface(this.$wbwindow.Element,false)),this.$wbwindow.DocumentFragment&&this.$wbwindow.DocumentFragment.prototype&&this.overrideParentNodeAppendPrepend(this.$wbwindow.DocumentFragment)},Wombat.prototype.initDocOverrides=function($document){if(Object.defineProperty){this.overrideReferrer($document),this.defGetterProp($document,"origin",function origin(){return this.WB_wombat_location.origin}),this.defGetterProp(this.$wbwindow,"origin",function origin(){return this.WB_wombat_location.origin});var wombat=this,domain_setter=function domain(val){var loc=this.WB_wombat_location;loc&&wombat.endsWith(loc.hostname,val)&&(this.__wb_domain=val)},domain_getter=function domain(){return this.__wb_domain||this.WB_wombat_location.hostname};this.defProp($document,"domain",domain_setter,domain_getter)}},Wombat.prototype.initDocWriteOpenCloseOverride=function(){if(this.$wbwindow.DOMParser){var DocumentProto=this.$wbwindow.Document.prototype,$wbDocument=this.$wbwindow.document,docWriteWritelnRWFn=this.rewriteDocWriteWriteln,orig_doc_write=$wbDocument.write,new_write=function write(){return docWriteWritelnRWFn(this,orig_doc_write,arguments)};$wbDocument.write=new_write,DocumentProto.write=new_write;var orig_doc_writeln=$wbDocument.writeln,new_writeln=function writeln(){return docWriteWritelnRWFn(this,orig_doc_writeln,arguments)};$wbDocument.writeln=new_writeln,DocumentProto.writeln=new_writeln;var wombat=this,orig_doc_open=$wbDocument.open,new_open=function open(){var res,thisObj=wombat.proxyToObj(this);if(arguments.length===3){var rwUrl=wombat.rewriteUrl(arguments[0],false,"mp_");res=orig_doc_open.call(thisObj,rwUrl,arguments[1],arguments[2]),wombat.initNewWindowWombat(res,arguments[0])}else res=orig_doc_open.call(thisObj),wombat.initNewWindowWombat(thisObj.defaultView);return res};$wbDocument.open=new_open,DocumentProto.open=new_open;var originalClose=$wbDocument.close,newClose=function close(){var thisObj=wombat.proxyToObj(this);return wombat.initNewWindowWombat(thisObj.defaultView),originalClose.__WB_orig_apply?originalClose.__WB_orig_apply(thisObj,arguments):originalClose.apply(thisObj,arguments)};$wbDocument.close=newClose,DocumentProto.close=newClose;var oBodyGetter=this.getOrigGetter(DocumentProto,"body"),oBodySetter=this.getOrigSetter(DocumentProto,"body");oBodyGetter&&oBodySetter&&this.defProp(DocumentProto,"body",function body(newBody){return newBody&&(newBody instanceof HTMLBodyElement||newBody instanceof HTMLFrameSetElement)&&wombat.rewriteElemComplete(newBody),oBodySetter.call(wombat.proxyToObj(this),newBody)},oBodyGetter)}},Wombat.prototype.initIframeWombat=function(iframe){var win;win=iframe._get_contentWindow?iframe._get_contentWindow.call(iframe):iframe.contentWindow;try{if(!win||win===this.$wbwindow||win._skip_wombat||win._wb_wombat)return}catch(e){return}var src=iframe.src;this.initNewWindowWombat(win,src)},Wombat.prototype.initNewWindowWombat=function(win,src){var fullWombat=false;if(win&&!win._wb_wombat){if((!src||src===""||this.startsWithOneOf(src,["about:blank","javascript:"]))&&(fullWombat=true),!fullWombat&&this.wb_info.isSW){var origURL=this.extractOriginalURL(src);(origURL==="about:blank"||origURL.startsWith("srcdoc:")||origURL.startsWith("blob:"))&&(fullWombat=true)}if(fullWombat){var newInfo={};Object.assign(newInfo,this.wb_info);var wombat=new Wombat(win,newInfo);win._wb_wombat=wombat.wombatInit()}else this.initProtoPmOrigin(win),this.initPostMessageOverride(win),this.initMessageEventOverride(win),this.initCheckThisFunc(win),this.initImportWrapperFunc(win)}},Wombat.prototype.initTimeoutIntervalOverrides=function(){var rewriteFn=this.rewriteSetTimeoutInterval;if(this.$wbwindow.setTimeout&&!this.$wbwindow.setTimeout.__$wbpatched$__){var originalSetTimeout=this.$wbwindow.setTimeout;this.$wbwindow.setTimeout=function setTimeout(){return rewriteFn(this,originalSetTimeout,arguments)},this.$wbwindow.setTimeout.__$wbpatched$__=true}if(this.$wbwindow.setInterval&&!this.$wbwindow.setInterval.__$wbpatched$__){var originalSetInterval=this.$wbwindow.setInterval;this.$wbwindow.setInterval=function setInterval(){return rewriteFn(this,originalSetInterval,arguments)},this.$wbwindow.setInterval.__$wbpatched$__=true}},Wombat.prototype.initWorkerOverrides=function(){var wombat=this;if(this.$wbwindow.Worker&&!this.$wbwindow.Worker._wb_worker_overriden){var orig_worker=this.$wbwindow.Worker;this.$wbwindow.Worker=function(Worker_){return function Worker(url,options){return wombat.domConstructorErrorChecker(this,"Worker",arguments),new Worker_(wombat.rewriteWorker(url),options)}}(orig_worker),this.$wbwindow.Worker.prototype=orig_worker.prototype,Object.defineProperty(this.$wbwindow.Worker.prototype,"constructor",{value:this.$wbwindow.Worker}),this.$wbwindow.Worker._wb_worker_overriden=true}if(this.$wbwindow.SharedWorker&&!this.$wbwindow.SharedWorker.__wb_sharedWorker_overriden){var oSharedWorker=this.$wbwindow.SharedWorker;this.$wbwindow.SharedWorker=function(SharedWorker_){return function SharedWorker(url,options){return wombat.domConstructorErrorChecker(this,"SharedWorker",arguments),new SharedWorker_(wombat.rewriteWorker(url),options)}}(oSharedWorker),this.$wbwindow.SharedWorker.prototype=oSharedWorker.prototype,Object.defineProperty(this.$wbwindow.SharedWorker.prototype,"constructor",{value:this.$wbwindow.SharedWorker}),this.$wbwindow.SharedWorker.__wb_sharedWorker_overriden=true}if(this.$wbwindow.ServiceWorkerContainer&&this.$wbwindow.ServiceWorkerContainer.prototype&&this.$wbwindow.ServiceWorkerContainer.prototype.register){var orig_register=this.$wbwindow.ServiceWorkerContainer.prototype.register;this.$wbwindow.ServiceWorkerContainer.prototype.register=function register(scriptURL,options){var newScriptURL=new URL(scriptURL,wombat.$wbwindow.document.baseURI).href,mod=wombat.getPageUnderModifier();return options&&options.scope?options.scope=wombat.rewriteUrl(options.scope,false,mod):options={scope:wombat.rewriteUrl("/",false,mod)},orig_register.call(this,wombat.rewriteUrl(newScriptURL,false,"sw_"),options)}}if(this.$wbwindow.Worklet&&this.$wbwindow.Worklet.prototype&&this.$wbwindow.Worklet.prototype.addModule&&!this.$wbwindow.Worklet.__wb_workerlet_overriden){var oAddModule=this.$wbwindow.Worklet.prototype.addModule;this.$wbwindow.Worklet.prototype.addModule=function addModule(moduleURL,options){var rwModuleURL=wombat.rewriteUrl(moduleURL,false,"js_");return oAddModule.call(this,rwModuleURL,options)},this.$wbwindow.Worklet.__wb_workerlet_overriden=true}},Wombat.prototype.initLocOverride=function(loc,oSetter,oGetter){if(Object.defineProperty)for(var prop,i=0;i=0&&props.splice(foundInx,1);return props}})}catch(e){console.log(e)}},Wombat.prototype.initHashChange=function(){if(this.$wbwindow.__WB_top_frame){var wombat=this,receive_hash_change=function receive_hash_change(event){if(event.data&&event.data.from_top){var message=event.data.message;message.wb_type&&(message.wb_type!=="outer_hashchange"||wombat.$wbwindow.location.hash==message.hash||(wombat.$wbwindow.location.hash=message.hash))}},send_hash_change=function send_hash_change(){var message={wb_type:"hashchange",hash:wombat.$wbwindow.location.hash};wombat.sendTopMessage(message)};this.$wbwindow.addEventListener("message",receive_hash_change),this.$wbwindow.addEventListener("hashchange",send_hash_change)}},Wombat.prototype.initPostMessageOverride=function($wbwindow){if($wbwindow.postMessage&&!$wbwindow.__orig_postMessage){var orig=$wbwindow.postMessage,wombat=this;$wbwindow.__orig_postMessage=orig;var postmessage_rewritten=function postMessage(message,targetOrigin,transfer,from_top){var from,src_id,this_obj=wombat.proxyToObj(this);if(this_obj||(this_obj=$wbwindow,this_obj.__WB_source=$wbwindow),this_obj.__WB_source&&this_obj.__WB_source.WB_wombat_location){var source=this_obj.__WB_source;if(from=source.WB_wombat_location.origin,this_obj.__WB_win_id||(this_obj.__WB_win_id={},this_obj.__WB_counter=0),!source.__WB_id){var id=this_obj.__WB_counter;source.__WB_id=id+source.WB_wombat_location.href,this_obj.__WB_counter+=1}this_obj.__WB_win_id[source.__WB_id]=source,src_id=source.__WB_id,this_obj.__WB_source=undefined}else from=window.WB_wombat_location.origin;var to_origin=targetOrigin;to_origin===this_obj.location.origin&&(to_origin=from);var new_message={from:from,to_origin:to_origin,src_id:src_id,message:message,from_top:from_top};if(targetOrigin!=="*"){if(this_obj.location.origin==="null"||this_obj.location.origin==="")return;targetOrigin=this_obj.location.origin}return orig.call(this_obj,new_message,targetOrigin,transfer)};$wbwindow.postMessage=postmessage_rewritten,$wbwindow.Window.prototype.postMessage=postmessage_rewritten;var eventTarget=null;eventTarget=$wbwindow.EventTarget&&$wbwindow.EventTarget.prototype?$wbwindow.EventTarget.prototype:$wbwindow;var _oAddEventListener=eventTarget.addEventListener;eventTarget.addEventListener=function addEventListener(type,listener,useCapture){var rwListener,obj=wombat.proxyToObj(this);if(type==="message"?rwListener=wombat.message_listeners.add_or_get(listener,function(){return wrapEventListener(listener,obj,wombat)}):type==="storage"?wombat.storage_listeners.add_or_get(listener,function(){return wrapSameOriginEventListener(listener,obj)}):rwListener=listener,rwListener)return _oAddEventListener.call(obj,type,rwListener,useCapture)};var _oRemoveEventListener=eventTarget.removeEventListener;eventTarget.removeEventListener=function removeEventListener(type,listener,useCapture){var rwListener,obj=wombat.proxyToObj(this);if(type==="message"?rwListener=wombat.message_listeners.remove(listener):type==="storage"?wombat.storage_listeners.remove(listener):rwListener=listener,rwListener)return _oRemoveEventListener.call(obj,type,rwListener,useCapture)};var override_on_prop=function(onevent,wrapperFN){var orig_setter=wombat.getOrigSetter($wbwindow,onevent),setter=function(value){this["__orig_"+onevent]=value;var obj=wombat.proxyToObj(this),listener=value?wrapperFN(value,obj,wombat):value;return orig_setter.call(obj,listener)},getter=function(){return this["__orig_"+onevent]};wombat.defProp($wbwindow,onevent,setter,getter)};override_on_prop("onmessage",wrapEventListener),override_on_prop("onstorage",wrapSameOriginEventListener)}},Wombat.prototype.initMessageEventOverride=function($wbwindow){!$wbwindow.MessageEvent||$wbwindow.MessageEvent.prototype.__extended||(this.addEventOverride("target"),this.addEventOverride("srcElement"),this.addEventOverride("currentTarget"),this.addEventOverride("eventPhase"),this.addEventOverride("path"),this.overridePropToProxy($wbwindow.MessageEvent.prototype,"source"),$wbwindow.MessageEvent.prototype.__extended=true)},Wombat.prototype.initUIEventsOverrides=function(){this.overrideAnUIEvent("UIEvent"),this.overrideAnUIEvent("MouseEvent"),this.overrideAnUIEvent("TouchEvent"),this.overrideAnUIEvent("FocusEvent"),this.overrideAnUIEvent("KeyboardEvent"),this.overrideAnUIEvent("WheelEvent"),this.overrideAnUIEvent("InputEvent"),this.overrideAnUIEvent("CompositionEvent")},Wombat.prototype.initOpenOverride=function(){var orig=this.$wbwindow.open;this.$wbwindow.Window.prototype.open&&(orig=this.$wbwindow.Window.prototype.open);var wombat=this,open_rewritten=function open(strUrl,strWindowName,strWindowFeatures){strWindowName&&(strWindowName=wombat.rewriteAttrTarget(strWindowName));var rwStrUrl=wombat.rewriteUrl(strUrl,false),res=orig.call(wombat.proxyToObj(this),rwStrUrl,strWindowName,strWindowFeatures);return wombat.initNewWindowWombat(res,strUrl),res};this.$wbwindow.open=open_rewritten,this.$wbwindow.Window.prototype.open&&(this.$wbwindow.Window.prototype.open=open_rewritten);for(var i=0;i +To: linux-kernel@vger.kernel.org +Subject: [ANNOUNCE 0/4] Genetic-lib version 0.2 +Date: Tue, 15 Feb 2005 13:29:06 -0600 +Cc: Peter Williams +Here is the next release of the genetic library based against 2.6.10 +kernel. + +There were numerous changes from the first release, but the major change +in this version is the introduction of phenotypes. A phenotype is a set +of genes the affect an observable property. In genetic-library terms, +it is a set of genes that will affect a particular fitness measurement. +Each phenotype will have a set of children that contain genes that +affect a fitness measure. + +Now multiple fitness routines can be ran for each genetic library user. +Then depending on the results of a particular fitness measure, the +specific genes that directly affect that fitness measure can be +modified. This introduces a finer granularity that was missing in the +first release of the genetic-library. + +I would like to thank Peter Williams for reworking the Zaphod Scheduler +and help designing the phenotypes. + +Some of the other features introduced is shifting the number of +mutations depending on how well a phenotype is performing. If the +current generation outperformed the previous generation, then the rate +of mutation will go down. Conversely if the current generation performed +worst then the previous generation, the mutation rate will go up. This +mutation rate shift will do two things. When generations are improving, +it will reduce the number unnecessary mutations and hone in on the +optimal tunables. When a workload drastically changes, the fitness +should go way down, and the mutation rate will increase in order to test +a greater space of better values quicker. This should decrease the time +it takes to adjust to a new workload. There is a limit at 45% of the +genes being mutated every generation in order to prevent the mutation +rate spiralling out of control. + +SpecJBB and UnixBench are still yielding a 1-3% performance improvement, +however (though it's subjective) the interactiveness has had noticeable +improvements. + +I have not broke the Anticipatory IO Scheduler down to a fine +granularity in phenotypes yet. Any assistance would be greatly +appreciated. + +Currently I am hosting this project off of: + + http://kernel.jakem.net + +[1/4 genetic-lib]: This is the base patch for the genetic algorithm. + +[2/4 genetic-io-sched]: The base patch for the IO schedulers to use the + genetic library. + +[3/4 genetic-as-sched]: A genetic-lib hooked anticipatory IO scheduler. + +[4/4 genetic-zaphod-cpu-sched]: A hooked zaphod CPU scheduler. Depends + on the zaphod-v6.2 patch. + +Thanks, +Jake + +- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ diff --git a/genetic-as-sched-2.6.11-gl1.patch b/genetic-as-sched-2.6.11-gl1.patch new file mode 100644 index 0000000..b9847fc --- /dev/null +++ b/genetic-as-sched-2.6.11-gl1.patch @@ -0,0 +1,416 @@ + +Change Log +0.2+ 2/17/05 +- Limited read_batch_expire not being greater then write_expire. +- Limited write_batch_expire not being greater then read_expire. +- Allowed antic_expire to go down to zero to cause it to go into + deadline mode + +--- + + +diff -puN drivers/block/Kconfig.iosched~genetic-as-sched drivers/block/Kconfig.iosched +--- linux-2.6.10/drivers/block/Kconfig.iosched~genetic-as-sched Mon Feb 21 08:38:40 2005 ++++ linux-2.6.10-moilanen/drivers/block/Kconfig.iosched Mon Feb 21 08:38:40 2005 +@@ -38,4 +38,13 @@ config IOSCHED_CFQ + among all processes in the system. It should provide a fair + working environment, suitable for desktop systems. + ++config GENETIC_IOSCHED_AS ++ bool "Genetic Anticipatory I/O scheduler (EXPERIMENTAL)" ++ depends on IOSCHED_AS && GENETIC_LIB && EXPERIMENTAL ++ default n ++ ---help--- ++ This will use a genetic algorithm to tweak the tunables of the ++ anticipatory scheduler autonomically and will adapt tunables ++ depending on the present workload. ++ + endmenu +diff -puN drivers/block/as-iosched.c~genetic-as-sched drivers/block/as-iosched.c +--- linux-2.6.10/drivers/block/as-iosched.c~genetic-as-sched Mon Feb 21 08:38:40 2005 ++++ linux-2.6.10-moilanen/drivers/block/as-iosched.c Wed Feb 23 14:11:15 2005 +@@ -20,6 +20,8 @@ + #include + #include + #include ++#include ++#include + + #define REQ_SYNC 1 + #define REQ_ASYNC 0 +@@ -67,6 +69,8 @@ + */ + #define MAX_THINKTIME (HZ/50UL) + ++unsigned long max_thinktime = MAX_THINKTIME; ++ + /* Bits in as_io_context.state */ + enum as_io_states { + AS_TASK_RUNNING=0, /* Process has not exitted */ +@@ -83,6 +87,94 @@ enum anticipation_status { + * or timed out */ + }; + ++#ifdef CONFIG_GENETIC_IOSCHED_AS ++ ++struct disk_stats_snapshot * as_stats_snapshot; ++ ++extern void disk_stats_snapshot(phenotype_t * pt); ++ ++static void as_num_ops_create_child(genetic_child_t * child); ++static void as_throughput_create_child(genetic_child_t * child); ++static void as_latency_create_child(genetic_child_t * child); ++static void as_general_create_child(genetic_child_t * child); ++ ++static void as_general_set_child_genes(void * in_genes); ++ ++static void as_num_ops_calc_fitness(genetic_child_t * child); ++static void as_throughput_calc_fitness(genetic_child_t * child); ++static void as_latency_calc_fitness(genetic_child_t * child); ++ ++static void as_general_calc_post_fitness(phenotype_t * in_pt); ++ ++static void as_shift_mutation_rate(phenotype_t * in_pt); ++ ++struct genetic_ops as_num_ops_genetic_ops = { ++ .create_child = as_num_ops_create_child, ++ .calc_fitness = as_num_ops_calc_fitness, ++}; ++ ++struct genetic_ops as_throughput_genetic_ops = { ++ .create_child = as_throughput_create_child, ++ .calc_fitness = as_throughput_calc_fitness, ++}; ++ ++struct genetic_ops as_latency_genetic_ops = { ++ .create_child = as_latency_create_child, ++ .calc_fitness = as_latency_calc_fitness, ++}; ++ ++struct genetic_ops as_general_genetic_ops = { ++ .create_child = as_general_create_child, ++ .set_child_genes = as_general_set_child_genes, ++ .combine_genes = genetic_generic_combine_genes, ++ .mutate_child = genetic_generic_mutate_child, ++ .calc_post_fitness = as_general_calc_post_fitness, ++ .take_snapshot = disk_stats_snapshot, ++ .shift_mutation_rate = as_shift_mutation_rate ++}; ++ ++#define AS_NUM_CHILDREN 8 ++ ++#define AS_NUM_OPS_UID 1 ++#define AS_NUM_OPS_NUM_GENES 0 ++ ++#define AS_THROUGHPUT_UID 2 ++#define AS_THROUGHPUT_NUM_GENES 0 ++ ++#define AS_LATENCY_UID 4 ++#define AS_LATENCY_NUM_GENES 0 ++ ++#define AS_GENERAL_UID (AS_NUM_OPS_UID | AS_THROUGHPUT_UID | AS_LATENCY_UID) ++#define AS_GENERAL_NUM_GENES 7 ++struct as_genes { ++ unsigned long read_expire; ++ unsigned long write_expire; ++ unsigned long read_batch_expire; ++ unsigned long write_batch_expire; ++ unsigned long antic_expire; ++ unsigned long max_thinktime; ++ unsigned long nr_requests; ++}; ++ ++gene_param_t as_gene_param[AS_GENERAL_NUM_GENES] = { ++ { HZ/16, 3*HZ/16, default_read_expire, 0}, /* read_expire */ ++ { HZ/8, 3*HZ/8, default_write_expire, 0}, /* write_expire */ ++ { HZ/4, 3*HZ/4, default_read_batch_expire, 0}, /* read_batch_expire */ ++ { HZ/16, 3*HZ/16, default_write_batch_expire, 0},/* write_batch_expire */ ++// { HZ/300, HZ/100, default_antic_expire, 0}, /* default_antic_expire */ ++ { 0, HZ/100, default_antic_expire, 0}, /* default_antic_expire */ ++ { HZ/100, 3*HZ/100, MAX_THINKTIME, 0}, /* max_thinktime */ ++ { BLKDEV_MIN_RQ, BLKDEV_MAX_RQ*30, BLKDEV_MAX_RQ, genetic_generic_iterative_mutate_gene} /* nr_requests */ ++}; ++ ++extern void disk_stats_snapshot(phenotype_t * pt); ++extern unsigned long disk_num_ops_calc_fitness(genetic_child_t * child); ++extern unsigned long disk_throughput_calc_fitness(genetic_child_t * child); ++extern unsigned long disk_latency_calc_fitness(genetic_child_t * child); ++ ++LIST_HEAD(as_data_list); ++#endif ++ + struct as_data { + /* + * run time data +@@ -132,6 +224,9 @@ struct as_data { + unsigned long fifo_expire[2]; + unsigned long batch_expire[2]; + unsigned long antic_expire; ++#ifdef CONFIG_GENETIC_IOSCHED_AS ++ struct list_head data_list; ++#endif + }; + + #define list_entry_fifo(ptr) list_entry((ptr), struct as_rq, fifo) +@@ -869,7 +964,7 @@ static void as_update_iohist(struct as_d + if (test_bit(AS_TASK_IORUNNING, &aic->state) + && in_flight == 0) { + thinktime = jiffies - aic->last_end_request; +- thinktime = min(thinktime, MAX_THINKTIME-1); ++ thinktime = min(thinktime, max_thinktime-1); + } else + thinktime = 0; + as_update_thinktime(ad, aic, thinktime); +@@ -1854,6 +1949,11 @@ static void as_exit_queue(elevator_t *e) + + mempool_destroy(ad->arq_pool); + put_io_context(ad->io_context); ++ ++#ifdef CONFIG_GENETIC_IOSCHED_AS ++ list_del(&ad->data_list); ++#endif ++ + kfree(ad->hash); + kfree(ad); + } +@@ -1916,6 +2016,10 @@ static int as_init_queue(request_queue_t + if (ad->write_batch_count < 2) + ad->write_batch_count = 2; + ++#ifdef CONFIG_GENETIC_IOSCHED_AS ++ list_add_tail(&ad->data_list, &as_data_list); ++#endif ++ + return 0; + } + +@@ -2099,6 +2203,9 @@ static struct elevator_type iosched_as = + static int __init as_init(void) + { + int ret; ++#ifdef CONFIG_GENETIC_IOSCHED_AS ++ genetic_t * genetic = 0; ++#endif + + arq_pool = kmem_cache_create("as_arq", sizeof(struct as_rq), + 0, 0, NULL, NULL); +@@ -2107,6 +2214,36 @@ static int __init as_init(void) + + ret = elv_register(&iosched_as); + if (!ret) { ++ ++#ifdef CONFIG_GENETIC_IOSCHED_AS ++ as_stats_snapshot = (struct disk_stats_snapshot *)kmalloc(sizeof(struct disk_stats_snapshot), GFP_KERNEL); ++ if (!as_stats_snapshot) ++ panic("as: failed to malloc enough space"); ++ ++ ++ ret = genetic_init(&genetic, AS_NUM_CHILDREN, 2 * HZ, "as-ioscheduler"); ++ if (ret) ++ panic("as: failed to init genetic lib"); ++ ++ if(genetic_register_phenotype(genetic, &as_num_ops_genetic_ops, AS_NUM_CHILDREN, ++ "num_ops", AS_NUM_OPS_NUM_GENES, AS_NUM_OPS_UID)) ++ panic("as: failed to register num_ops phenotype"); ++ ++ if(genetic_register_phenotype(genetic, &as_throughput_genetic_ops, AS_NUM_CHILDREN, ++ "throughput", AS_THROUGHPUT_NUM_GENES, AS_THROUGHPUT_UID)) ++ panic("as: failed to register throughput phenotype"); ++ ++ if(genetic_register_phenotype(genetic, &as_latency_genetic_ops, AS_NUM_CHILDREN, ++ "latency", AS_LATENCY_NUM_GENES, AS_LATENCY_UID)) ++ panic("as: failed to register latency phenotype"); ++ ++ if(genetic_register_phenotype(genetic, &as_general_genetic_ops, AS_NUM_CHILDREN, ++ "general", AS_GENERAL_NUM_GENES, AS_GENERAL_UID)) ++ panic("as: failed to register general phenotype"); ++ ++ genetic_start(genetic); ++#endif ++ + /* + * don't allow AS to get unregistered, since we would have + * to browse all tasks in the system and release their +@@ -2126,6 +2263,180 @@ static void __exit as_exit(void) + elv_unregister(&iosched_as); + } + ++#ifdef CONFIG_GENETIC_IOSCHED_AS ++ ++static void as_num_ops_create_child(genetic_child_t * child) ++{ ++ BUG_ON(!child); ++ ++ child->genes = 0; ++ child->gene_param = 0; ++ child->num_genes = AS_NUM_OPS_NUM_GENES; ++ child->stats_snapshot = as_stats_snapshot; ++} ++ ++static void as_throughput_create_child(genetic_child_t * child) ++{ ++ BUG_ON(!child); ++ ++ child->genes = 0; ++ child->gene_param = 0; ++ child->num_genes = AS_THROUGHPUT_NUM_GENES; ++ child->stats_snapshot = as_stats_snapshot; ++} ++ ++static void as_latency_create_child(genetic_child_t * child) ++{ ++ BUG_ON(!child); ++ ++ child->genes = 0; ++ child->gene_param = 0; ++ child->num_genes = AS_LATENCY_NUM_GENES; ++ child->stats_snapshot = as_stats_snapshot; ++} ++ ++/* need to create the genes for the child */ ++static void as_general_create_child(genetic_child_t * child) ++{ ++ BUG_ON(!child); ++ ++ child->genes = (void *)kmalloc(sizeof(struct as_genes), GFP_KERNEL); ++ if (!child->genes) ++ panic("as_general_create_child: error mallocing space"); ++ ++ child->gene_param = as_gene_param; ++ child->num_genes = AS_GENERAL_NUM_GENES; ++ child->stats_snapshot = as_stats_snapshot; ++ ++ genetic_create_child_spread(child, AS_NUM_CHILDREN-1); ++ ++ ((struct as_genes *)child->genes)->nr_requests = BLKDEV_MAX_RQ; ++} ++ ++static void as_shift_mutation_rate(phenotype_t * in_pt) ++{ ++ struct list_head * p; ++ phenotype_t * pt; ++ int count = 0; ++ long rate = 0; ++ ++ list_for_each(p, &in_pt->genetic->phenotype) { ++ pt = list_entry(p, phenotype_t, phenotype); ++ ++ /* Look at everyone else that contributes to this ++ phenotype */ ++ if (pt->uid & AS_GENERAL_UID && pt->uid != AS_GENERAL_UID) { ++ ++ switch (pt->uid) { ++ case AS_NUM_OPS_UID: ++ case AS_THROUGHPUT_UID: ++ case AS_LATENCY_UID: ++ rate += pt->mutation_rate; ++ count++; ++ break; ++ default: ++ BUG(); ++ } ++ } ++ } ++ ++ /* If we are a general phenotype that is made up of other ++ phenotypes then we take the average */ ++ if (count) ++ in_pt->mutation_rate = (rate / count); ++ else ++ BUG(); ++} ++ ++static void as_general_set_child_genes(void * in_genes) ++{ ++ struct as_genes * genes = (struct as_genes *)in_genes; ++ struct list_head * d; ++ struct as_data * ad; ++ ++ list_for_each(d, &as_data_list) { ++ ad = list_entry(d, struct as_data, data_list); ++ ad->fifo_expire[REQ_SYNC] = genes->read_expire; ++ ad->fifo_expire[REQ_ASYNC] = genes->write_expire; ++ ad->antic_expire = genes->antic_expire; ++ ++ if (genes->read_batch_expire > genes->write_expire) ++ genes->read_batch_expire = genes->write_expire; ++ ad->batch_expire[REQ_SYNC] = genes->read_batch_expire; ++ ++ if (genes->write_batch_expire > genes->read_expire) ++ genes->write_batch_expire = genes->read_expire; ++ ad->batch_expire[REQ_ASYNC] = genes->write_batch_expire; ++ ++ ad->q->nr_requests = genes->nr_requests; ++ } ++ max_thinktime = genes->max_thinktime; ++ ++} ++ ++static void as_num_ops_calc_fitness(genetic_child_t * child) ++{ ++ child->fitness = disk_num_ops_calc_fitness(child); ++} ++ ++static void as_throughput_calc_fitness(genetic_child_t * child) ++{ ++ child->fitness = disk_throughput_calc_fitness(child); ++} ++ ++static void as_latency_calc_fitness(genetic_child_t * child) ++{ ++ child->fitness = disk_latency_calc_fitness(child); ++} ++ ++/* Make the general the one that takes into account all the fitness ++ * routines, since these are the common genes that effect everything. ++ */ ++static void as_general_calc_post_fitness(phenotype_t * in_pt) ++{ ++ struct list_head * p; ++ phenotype_t * pt; ++ genetic_t * genetic = in_pt->genetic; ++ int ranking[AS_NUM_CHILDREN]; ++ int weight = 1; ++ int i; ++ ++ memset(ranking, 0, sizeof(ranking)); ++ ++ list_for_each(p, &genetic->phenotype) { ++ pt = list_entry(p, phenotype_t, phenotype); ++ ++ /* Look at everyone else that contributes to this ++ phenotype */ ++ if (pt->uid & AS_GENERAL_UID && pt->uid != AS_GENERAL_UID) { ++ ++ switch (pt->uid) { ++ case AS_NUM_OPS_UID: ++ weight = 2; ++ break; ++ case AS_THROUGHPUT_UID: ++ weight = 2; ++ break; ++ case AS_LATENCY_UID: ++ weight = 1; ++ break; ++ default: ++ BUG(); ++ } ++ ++ for (i = 0; i < pt->num_children; i++) ++ ranking[pt->child_ranking[i]->id] += (i * weight); ++ } ++ } ++ ++ for (i = 0; i < in_pt->num_children; i++) ++ in_pt->child_ranking[i]->fitness = ranking[i]; ++ ++} ++ ++#endif ++ ++ + module_init(as_init); + module_exit(as_exit); + + +_ diff --git a/genetic-io-sched-2.6.11-gl1.patch b/genetic-io-sched-2.6.11-gl1.patch new file mode 100644 index 0000000..9b6b79c --- /dev/null +++ b/genetic-io-sched-2.6.11-gl1.patch @@ -0,0 +1,174 @@ +Index: 2.6.11/drivers/block/genhd.c +=================================================================== +--- 2.6.11.orig/drivers/block/genhd.c 2005-03-02 01:38:08.000000000 -0600 ++++ 2.6.11/drivers/block/genhd.c 2005-04-15 11:35:40.763715300 -0500 +@@ -31,6 +31,8 @@ + char name[16]; + } *major_names[MAX_PROBE_HASH]; + ++LIST_HEAD(gendisks); ++ + /* index in the above - for now: assume no multimajor ranges */ + static inline int major_to_index(int major) + { +@@ -589,6 +591,7 @@ + kobj_set_kset_s(disk,block_subsys); + kobject_init(&disk->kobj); + rand_initialize_disk(disk); ++ list_add_tail(&disk->gendisks, &gendisks); + } + return disk; + } +Index: 2.6.11/drivers/block/ll_rw_blk.c +=================================================================== +--- 2.6.11.orig/drivers/block/ll_rw_blk.c 2005-03-02 01:37:48.000000000 -0600 ++++ 2.6.11/drivers/block/ll_rw_blk.c 2005-04-15 11:35:40.765716044 -0500 +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + /* + * for max sense size +@@ -2140,6 +2141,99 @@ + __elv_add_request(q, req, ELEVATOR_INSERT_SORT, 0); + } + ++#ifdef CONFIG_GENETIC_IOSCHED_AS ++extern struct list_head gendisks; ++ ++void disk_stats_snapshot(phenotype_t * pt) ++{ ++ struct list_head * d; ++ struct gendisk *disk; ++ struct disk_stats_snapshot * ss = (struct disk_stats_snapshot *)pt->child_ranking[0]->stats_snapshot; ++ ++ memset(ss, 0, sizeof(struct disk_stats_snapshot)); ++ ++ list_for_each(d, &gendisks) { ++ disk = list_entry(d, struct gendisk, gendisks); ++ ++ disk_round_stats(disk); ++ ++ ss->reads += disk_stat_read(disk, reads); ++ ss->writes += disk_stat_read(disk, writes); ++ ss->read_sectors += disk_stat_read(disk, read_sectors); ++ ss->write_sectors += disk_stat_read(disk, write_sectors); ++ ss->time_in_queue += disk_stat_read(disk, time_in_queue); ++ } ++} ++ ++unsigned long disk_num_ops_calc_fitness(genetic_child_t * child) ++{ ++ struct list_head * d; ++ struct gendisk *disk; ++ struct disk_stats_snapshot * ss = (struct disk_stats_snapshot *)child->stats_snapshot; ++ unsigned long reads = 0; ++ unsigned long writes = 0; ++ ++ list_for_each(d, &gendisks) { ++ disk = list_entry(d, struct gendisk, gendisks); ++ ++ disk_round_stats(disk); ++ ++ reads += disk_stat_read(disk, reads); ++ writes += disk_stat_read(disk, writes); ++ } ++ ++ reads -= ss->reads; ++ writes -= ss->writes; ++ ++ return reads + writes; ++} ++ ++unsigned long disk_throughput_calc_fitness(genetic_child_t * child) ++{ ++ struct list_head * d; ++ struct gendisk *disk; ++ struct disk_stats_snapshot * ss = (struct disk_stats_snapshot *)child->stats_snapshot; ++ unsigned long read_sectors = 0; ++ unsigned long write_sectors = 0; ++ ++ list_for_each(d, &gendisks) { ++ disk = list_entry(d, struct gendisk, gendisks); ++ ++ disk_round_stats(disk); ++ ++ read_sectors += disk_stat_read(disk, read_sectors); ++ write_sectors += disk_stat_read(disk, write_sectors); ++ } ++ ++ read_sectors -= ss->read_sectors; ++ write_sectors -= ss->write_sectors; ++ ++ return read_sectors + write_sectors; ++} ++ ++unsigned long disk_latency_calc_fitness(genetic_child_t * child) ++{ ++ struct list_head * d; ++ struct gendisk *disk; ++ struct disk_stats_snapshot * ss = (struct disk_stats_snapshot *)child->stats_snapshot; ++ unsigned long time_in_queue = 0; ++ ++ list_for_each(d, &gendisks) { ++ disk = list_entry(d, struct gendisk, gendisks); ++ ++ disk_round_stats(disk); ++ ++ time_in_queue += disk_stat_read(disk, time_in_queue); ++ } ++ ++ time_in_queue = -(time_in_queue - ss->time_in_queue); ++ ++ return time_in_queue; ++} ++ ++ ++#endif /* GENETIC_IOSCHED_AS */ ++ + /* + * disk_round_stats() - Round off the performance stats on a struct + * disk_stats. +@@ -2162,7 +2256,6 @@ + __disk_stat_add(disk, time_in_queue, + disk->in_flight * (now - disk->stamp)); + disk->stamp = now; +- + if (disk->in_flight) + __disk_stat_add(disk, io_ticks, (now - disk->stamp_idle)); + disk->stamp_idle = now; +Index: 2.6.11/include/linux/genhd.h +=================================================================== +--- 2.6.11.orig/include/linux/genhd.h 2005-03-02 01:37:49.000000000 -0600 ++++ 2.6.11/include/linux/genhd.h 2005-04-15 11:35:40.766716416 -0500 +@@ -121,6 +121,7 @@ + atomic_t sync_io; /* RAID */ + unsigned long stamp, stamp_idle; + int in_flight; ++ struct list_head gendisks; + #ifdef CONFIG_SMP + struct disk_stats *dkstats; + #else +Index: 2.6.11/include/linux/blkdev.h +=================================================================== +--- 2.6.11.orig/include/linux/blkdev.h 2005-03-02 01:37:50.000000000 -0600 ++++ 2.6.11/include/linux/blkdev.h 2005-04-15 11:35:40.767716788 -0500 +@@ -724,5 +724,16 @@ + #define MODULE_ALIAS_BLOCKDEV_MAJOR(major) \ + MODULE_ALIAS("block-major-" __stringify(major) "-*") + ++#ifdef CONFIG_GENETIC_IOSCHED_AS ++ ++struct disk_stats_snapshot ++{ ++ unsigned long reads; ++ unsigned long writes; ++ unsigned long read_sectors; ++ unsigned long write_sectors; ++ unsigned long time_in_queue; ++}; ++#endif /* CONFIG_GENETIC_IOSCHED_AS */ + + #endif diff --git a/genetic-lib-2.6.11-gl1.patch b/genetic-lib-2.6.11-gl1.patch new file mode 100644 index 0000000..6ea985b --- /dev/null +++ b/genetic-lib-2.6.11-gl1.patch @@ -0,0 +1,1190 @@ +Index: 2.6.11-as-gl1/fs/proc/proc_misc.c +=================================================================== +--- 2.6.11-as-gl1.orig/fs/proc/proc_misc.c 2005-03-02 01:37:49.000000000 -0600 ++++ 2.6.11-as-gl1/fs/proc/proc_misc.c 2005-04-16 15:01:53.158735016 -0500 +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -200,6 +201,97 @@ + #undef K + } + ++#ifdef CONFIG_GENETIC_LIB ++extern struct proc_dir_entry * genetic_root_dir; ++ ++int genetic_read_proc(char *page, char **start, off_t off, ++ int count, int *eof, void *data) ++{ ++ int n = 0; ++ genetic_t * genetic = (genetic_t *)data; ++ ++ struct list_head * p; ++ phenotype_t * pt; ++ ++ ++ n = sprintf(page, "%s:\n", genetic->name); ++ n += sprintf(page+n, "generation_number:\t\t%ld\n", genetic->generation_number); ++ n += sprintf(page+n, "num_children:\t\t\t%ld\n", genetic->num_children); ++ n += sprintf(page+n, "child_life_time:\t\t%ld\n\n", genetic->child_life_time); ++ n += sprintf(page+n, "child_number:\t\t\t%ld\n\n", genetic->child_number); ++ ++ n += sprintf(page+n, "Phenotypes Average Fitness\n"); ++ ++ list_for_each(p, &genetic->phenotype) { ++ pt = list_entry(p, phenotype_t, phenotype); ++ ++ n += sprintf(page+n, "%-24s:\t\t%lld\n", pt->name, pt->avg_fitness); ++ } ++ ++ return proc_calc_metrics(page, start, off, count, eof, n); ++} ++ ++int genetic_phenotype_read_proc(char *page, char **start, off_t off, ++ int count, int *eof, void *data) ++{ ++ int i; ++ int n = 0; ++ phenotype_t * pt = (phenotype_t *)data; ++ ++ n = sprintf(page, "------ %s -----\n", pt->name); ++ n += sprintf(page+n, "generation_number:\t%ld\n", pt->genetic->generation_number); ++ n += sprintf(page+n, "num_children:\t\t%ld\n\n", pt->num_children); ++ n += sprintf(page+n, "child_number:\t\t%ld\n", pt->child_number); ++ n += sprintf(page+n, "mutation_rate:\t\t%ld\n", pt->mutation_rate); ++ n += sprintf(page+n, "num_mutations:\t\t%ld\n", pt->num_mutations); ++ n += sprintf(page+n, "num_genes:\t\t%ld\n", pt->num_genes); ++ n += sprintf(page+n, "uid:\t\t\t%ld\n", pt->uid); ++ n += sprintf(page+n, "avg_fitness:\t\t%lld\n", pt->avg_fitness); ++ n += sprintf(page+n, "last_gen_avg_fitness:\t%lld\n", pt->last_gen_avg_fitness); ++ ++ n += sprintf(page+n, "\nFitness history\n"); ++ ++ for (i = pt->genetic->generation_number > GENETIC_HISTORY_SIZE ? GENETIC_HISTORY_SIZE ++ : pt->genetic->generation_number-1; i > 0; i--) ++ n += sprintf(page+n, "%ld:\t%lld\n", ++ pt->genetic->generation_number - i, ++ pt->fitness_history[(pt->fitness_history_index - i) & GENETIC_HISTORY_MASK]); ++ ++ return proc_calc_metrics(page, start, off, count, eof, n); ++} ++ ++#if GENETIC_DEBUG ++int genetic_debug_read_proc(char *page, char **start, off_t off, ++ int count, int *eof, void *data) ++{ ++ int i, j, k; ++ int n = 0; ++ phenotype_t * pt = (phenotype_t *)data; ++ ++ n = sprintf(page, "generation_number:\t%ld\n", pt->genetic->generation_number); ++ ++ for (i = 0, j = 1; i < pt->debug_size; j++) { ++ /* print out child number, and ID */ ++ n += sprintf(page+n, "%d (%lld):", j, pt->debug_history[i++]); ++ /* print out child fitness */ ++ n += sprintf(page+n, " %-12lld:\t", pt->debug_history[i++]); ++ ++ for (k = 0; k < pt->child_ranking[0]->num_genes; k++) { ++ n += sprintf(page+n, "%lld\t", pt->debug_history[i++]); ++ } ++ n += sprintf(page+n, "\n"); ++ ++ if (j == pt->num_children) { ++ n += sprintf(page+n, "\n"); ++ j = 0; ++ } ++ } ++ ++ return proc_calc_metrics(page, start, off, count, eof, n); ++} ++#endif /* GENETIC_DEBUG */ ++#endif /* CONFIG_GENETIC_LIB */ ++ + extern struct seq_operations fragmentation_op; + static int fragmentation_open(struct inode *inode, struct file *file) + { +Index: 2.6.11-as-gl1/include/linux/genetic.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ 2.6.11-as-gl1/include/linux/genetic.h 2005-04-16 15:23:59.312856488 -0500 +@@ -0,0 +1,233 @@ ++#ifndef __LINUX_GENETIC_H ++#define __LINUX_GENETIC_H ++/* ++ * include/linux/genetic.h ++ * ++ * Jake Moilanen ++ * Copyright (C) 2004 IBM ++ * ++ * Genetic algorithm library ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++ ++ ++#define GENETIC_HISTORY_SIZE 0x8 ++#define GENETIC_HISTORY_MASK (GENETIC_HISTORY_SIZE - 1) ++ ++/* percentage of total number genes to mutate */ ++#define GENETIC_DEFAULT_MUTATION_RATE 15 ++ ++/* XXX TODO Make this an adjustable runtime variable */ ++/* Percentage that an iteration can jump within the range */ ++#define GENETIC_ITERATIVE_MUTATION_RANGE 20 ++ ++/* the rate that GENETIC_DEFAULT_MUTATION_RATE itself can change */ ++#define GENETIC_DEFAULT_MUTATION_RATE_CHANGE 4 ++#define GENETIC_MAX_MUTATION_RATE 45 ++#define GENETIC_MIN_MUTATION_RATE 10 ++ ++#define GENETIC_DEBUG 1 ++#define GENETIC_NUM_DEBUG_POINTS 4 ++ ++#define GENETIC_PRINT_DEBUG 0 ++#define gen_dbg(format, arg...) do { if (GENETIC_PRINT_DEBUG) printk(KERN_EMERG __FILE__ ": " format "\n" , ## arg); } while (0) ++#define gen_trc(format, arg...) do { if (GENETIC_PRINT_DEBUG) printk(KERN_EMERG __FILE__ ":%s:%d\n" , __FUNCTION__, __LINE__); } while (0) ++ ++struct gene_param_s; ++struct genetic_s; ++struct phenotype_s; ++ ++struct genetic_child_s { ++ struct list_head list; ++ long long fitness; ++ unsigned long num_genes; ++ void *genes; ++ struct gene_param_s *gene_param; ++ void *stats_snapshot; ++ int id; ++}; ++ ++typedef struct genetic_child_s genetic_child_t; ++ ++/* Here's a generic idea of what it the genes could look like */ ++struct gene_param_s { ++ unsigned long min; ++ unsigned long max; ++ unsigned long initial; ++ void (*mutate_gene)(genetic_child_t *, unsigned long); ++}; ++ ++typedef struct gene_param_s gene_param_t; ++ ++struct phenotype_s { ++ struct list_head phenotype; ++ ++ struct list_head children_queue[2]; ++ struct list_head *run_queue; ++ struct list_head *finished_queue; ++ struct genetic_ops *ops; ++ ++ char *name; ++ ++ struct genetic_s *genetic; /* point back ++ * to genetic ++ * struct ++ */ ++ ++ unsigned long num_children; /* Must be power of 2 */ ++ unsigned long natural_selection_cutoff; /* How many children ++ * will survive ++ */ ++ void *stats_snapshot; ++ unsigned long child_number; ++ ++ /* percentage of total number of genes to mutate */ ++ long mutation_rate; ++ unsigned long num_mutations; ++ unsigned long num_genes; ++ ++ genetic_child_t **child_ranking; ++ ++ void (*natural_selection)(struct phenotype_s *); ++ ++ /* This UID is bitmap comprised of other phenotypes that contribute ++ to the genes */ ++ unsigned long uid; ++ ++ /* performance metrics */ ++ long long avg_fitness; ++ long long last_gen_avg_fitness; ++ ++ unsigned long fitness_history_index; ++ long long fitness_history[GENETIC_HISTORY_SIZE]; ++ ++#if GENETIC_DEBUG ++ unsigned long debug_size; /* number of longs in ++ debug history */ ++ unsigned long debug_index; ++ long long *debug_history; ++#endif ++}; ++ ++typedef struct phenotype_s phenotype_t; ++ ++struct genetic_s { ++ char *name; ++ struct timer_list timer; ++ ++ struct list_head phenotype; ++ ++ unsigned long child_number; ++ unsigned long child_life_time; ++ unsigned long num_children; /* Must be power of 2 */ ++ ++ struct proc_dir_entry *dir; ++ struct proc_dir_entry *debug_dir; ++ unsigned long generation_number; ++ ++}; ++ ++typedef struct genetic_s genetic_t; ++ ++struct genetic_ops { ++ void (*create_child)(genetic_child_t *); ++ void (*set_child_genes)(void *); ++ void (*calc_fitness)(genetic_child_t *); ++ void (*combine_genes)(genetic_child_t *, genetic_child_t *, ++ genetic_child_t *); ++ void (*mutate_child)(genetic_child_t *); ++ void (*calc_post_fitness)(phenotype_t *); /* Fitness routine used when ++ * need to take into account ++ * other phenotype fitness ++ * results after they ran ++ */ ++ void (*take_snapshot)(phenotype_t *); ++ void (*shift_mutation_rate)(phenotype_t *); ++}; ++ ++/* Setup routines */ ++int __init genetic_init(genetic_t ** in_genetic, unsigned long num_children, ++ unsigned long child_life_time, ++ char * name); ++int __init genetic_register_phenotype(genetic_t * genetic, struct genetic_ops * ops, ++ unsigned long num_children, char * name, ++ unsigned long num_genes, unsigned long uid); ++void __init genetic_start(genetic_t * genetic); ++ ++/* Generic helper functions */ ++void genetic_generic_mutate_child(genetic_child_t * child); ++void genetic_generic_iterative_mutate_gene(genetic_child_t * child, long gene_num); ++void genetic_iterative_from_default_mutate_gene(genetic_child_t * child, long gene_num); ++void genetic_generic_combine_genes(genetic_child_t * parent_a, ++ genetic_child_t * parent_b, ++ genetic_child_t * child); ++void genetic_create_child_spread(genetic_child_t * child, unsigned long num_children); ++void genetic_create_child_defaults(genetic_child_t * child); ++void genetic_general_shift_mutation_rate(phenotype_t * in_pt); ++ ++#if BITS_PER_LONG >= 64 ++ ++static inline void divll(long long *n, long div, long *rem) ++{ ++ *rem = *n % div; ++ *n /= div; ++} ++ ++#else ++ ++static inline void divl(int32_t high, int32_t low, ++ int32_t div, ++ int32_t *q, int32_t *r) ++{ ++ int64_t n = (u_int64_t)high << 32 | low; ++ int64_t d = (u_int64_t)div << 31; ++ int32_t q1 = 0; ++ int c = 32; ++ while (n > 0xffffffff) { ++ q1 <<= 1; ++ if (n >= d) { ++ n -= d; ++ q1 |= 1; ++ } ++ d >>= 1; ++ c--; ++ } ++ q1 <<= c; ++ if (n) { ++ low = n; ++ *q = q1 | (low / div); ++ *r = low % div; ++ } else { ++ *r = 0; ++ *q = q1; ++ } ++ return; ++} ++ ++static inline void divll(long long *n, long div, long *rem) ++{ ++ int32_t low, high; ++ low = *n & 0xffffffff; ++ high = *n >> 32; ++ if (high) { ++ int32_t high1 = high % div; ++ int32_t low1 = low; ++ high /= div; ++ divl(high1, low1, div, &low, (int32_t *)rem); ++ *n = (int64_t)high << 32 | low; ++ } else { ++ *n = low / div; ++ *rem = low % div; ++ } ++} ++#endif ++ ++#endif +Index: 2.6.11-as-gl1/lib/Kconfig +=================================================================== +--- 2.6.11-as-gl1.orig/lib/Kconfig 2005-03-02 01:38:10.000000000 -0600 ++++ 2.6.11-as-gl1/lib/Kconfig 2005-04-16 15:01:53.160735760 -0500 +@@ -30,6 +30,12 @@ + require M here. See Castagnoli93. + Module will be libcrc32c. + ++config GENETIC_LIB ++ bool "Genetic Library" ++ help ++ This option will build in a genetic library that will tweak ++ kernel parameters autonomically to improve performance. ++ + # + # compression support is select'ed if needed + # +Index: 2.6.11-as-gl1/lib/Makefile +=================================================================== +--- 2.6.11-as-gl1.orig/lib/Makefile 2005-03-02 01:37:47.000000000 -0600 ++++ 2.6.11-as-gl1/lib/Makefile 2005-04-16 15:01:53.160735760 -0500 +@@ -24,6 +24,7 @@ + obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o + obj-$(CONFIG_CRC32) += crc32.o + obj-$(CONFIG_LIBCRC32C) += libcrc32c.o ++obj-$(CONFIG_GENETIC_LIB) += genetic.o + obj-$(CONFIG_GENERIC_IOMAP) += iomap.o + + obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/ +Index: 2.6.11-as-gl1/lib/genetic.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ 2.6.11-as-gl1/lib/genetic.c 2005-04-16 15:24:26.437093456 -0500 +@@ -0,0 +1,808 @@ ++/* ++ * Genetic Algorithm Library ++ * ++ * Jake Moilanen ++ * Copyright (C) 2004 IBM ++ * ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ */ ++ ++/* ++ * Life cycle ++ * ++ * 1.) Create random children ++ * 2.) Run tests ++ * 3.) Calculate fitness ++ * 4.) Take top preformers ++ * 5.) Make children ++ * 6.) Mutate ++ * 7.) Goto step 2 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++char genetic_lib_version[] = "0.2"; ++ ++int mutation_rate_change = GENETIC_DEFAULT_MUTATION_RATE_CHANGE; ++int genetic_lib_enabled = 1; ++ ++static void genetic_ns_top_parents(phenotype_t *); ++static void genetic_ns_award_top_parents(phenotype_t *); ++static int genetic_create_children(phenotype_t *); ++static void genetic_split_performers(phenotype_t *); ++static void genetic_mutate(phenotype_t *); ++static void genetic_run_child(genetic_t * genetic); ++static void genetic_new_generation(genetic_t * genetic); ++ ++void genetic_switch_child(unsigned long data); ++struct proc_dir_entry * genetic_root_dir = 0; ++ ++extern int genetic_read_proc(char *page, char **start, off_t off, ++ int count, int *eof, void *data); ++extern int genetic_phenotype_read_proc(char *page, char **start, off_t off, ++ int count, int *eof, void *data); ++ ++#if GENETIC_DEBUG ++extern int genetic_debug_read_proc(char *page, char **start, off_t off, ++ int count, int *eof, void *data); ++#endif ++ ++ ++int __init genetic_init(genetic_t ** in_genetic, unsigned long num_children, ++ unsigned long child_life_time, ++ char * name) ++{ ++ struct proc_dir_entry *entry; ++ genetic_t * genetic; ++ ++ if (!genetic_lib_enabled) ++ return 0; ++ ++ printk(KERN_INFO "Initializing Genetic Library - version %s\n", genetic_lib_version); ++ ++ genetic = (genetic_t *)kmalloc(sizeof(genetic_t), GFP_KERNEL); ++ if (!genetic) { ++ printk(KERN_ERR "genetic_init: not enough memory\n"); ++ return -ENOMEM; ++ } ++ ++ *in_genetic = genetic; ++ ++ genetic->name = (char *)kmalloc(strlen(name), GFP_KERNEL); ++ if (!genetic->name) { ++ printk(KERN_ERR "genetic_init: not enough memory\n"); ++ kfree(genetic); ++ return -ENOMEM; ++ } ++ ++ /* Init some of our values */ ++ strcpy(genetic->name, name); ++ ++ genetic->num_children = num_children; ++ genetic->child_life_time = child_life_time; ++ ++ genetic->generation_number = 1; ++ genetic->child_number = 0; ++ ++ /* Setup how long each child has to live */ ++ init_timer(&genetic->timer); ++ genetic->timer.function = genetic_switch_child; ++ genetic->timer.data = (unsigned long)genetic; ++ ++#ifdef CONFIG_PROC_FS ++ /* Setup proc structure to monitor */ ++ if (!genetic_root_dir) ++ genetic_root_dir = proc_mkdir("genetic", 0); ++ ++ genetic->dir = proc_mkdir(name, genetic_root_dir); ++ ++ entry = create_proc_entry("stats", 0644, genetic->dir); ++ ++ if (entry) { ++ entry->nlink = 1; ++ entry->data = genetic; ++ entry->read_proc = genetic_read_proc; ++ } ++ ++#ifdef GENETIC_DEBUG ++ genetic->debug_dir = proc_mkdir("debug", genetic->dir); ++#endif /* GENETIC_DEBUG */ ++ ++ ++#endif /* CONFIG_PROC_FS */ ++ ++ INIT_LIST_HEAD(&genetic->phenotype); ++ ++ return 0; ++} ++ ++int __init genetic_register_phenotype(genetic_t * genetic, struct genetic_ops * ops, ++ unsigned long num_children, char * name, ++ unsigned long num_genes, unsigned long uid) ++{ ++ struct proc_dir_entry *entry; ++ phenotype_t * pt; ++ int rc; ++ ++ if (!genetic_lib_enabled) ++ return 0; ++ ++ printk(KERN_INFO "Initializing %s's phenotype %s\n", genetic->name, name); ++ ++ pt = (phenotype_t *)kmalloc(sizeof(phenotype_t), GFP_KERNEL); ++ if (!genetic) { ++ printk(KERN_ERR "genetic_register_phenotype: not enough memory\n"); ++ return -ENOMEM; ++ } ++ ++ pt->name = (char *)kmalloc(strlen(name), GFP_KERNEL); ++ if (!pt->name) { ++ printk(KERN_ERR "genetic_register_phenotype: not enough memory\n"); ++ kfree(pt); ++ return -ENOMEM; ++ } ++ ++ pt->child_ranking = (genetic_child_t **)kmalloc(num_children * sizeof(genetic_child_t *), GFP_KERNEL); ++ if (!pt->child_ranking) { ++ printk(KERN_ERR "genetic_register_phenotype: not enough memory\n"); ++ kfree(pt->name); ++ kfree(pt); ++ return -ENOMEM; ++ } ++ ++ strcpy(pt->name, name); ++ ++ INIT_LIST_HEAD(&pt->children_queue[0]); ++ INIT_LIST_HEAD(&pt->children_queue[1]); ++ ++ pt->run_queue = &pt->children_queue[0]; ++ pt->finished_queue = &pt->children_queue[1]; ++ ++ pt->ops = ops; ++ pt->num_children = num_children; ++ ++ pt->mutation_rate = GENETIC_DEFAULT_MUTATION_RATE; ++ pt->natural_selection = genetic_ns_top_parents; ++ pt->natural_selection_cutoff = num_children / 2; ++ pt->avg_fitness = 0; ++ pt->last_gen_avg_fitness = 0; ++ pt->child_number = 0; ++ ++ pt->genetic = genetic; ++ pt->uid = uid; ++ pt->num_genes = num_genes; ++ ++ /* Create some children */ ++ rc = genetic_create_children(pt); ++ if (rc) ++ return rc; ++ ++#ifdef CONFIG_PROC_FS ++ entry = create_proc_entry(name, 0644, genetic->dir); ++ ++ if (entry) { ++ entry->nlink = 1; ++ entry->data = pt; ++ entry->read_proc = genetic_phenotype_read_proc; ++ } ++ ++#endif ++ ++#if GENETIC_DEBUG ++ pt->debug_index = 0; ++ /* create array for history. The +2 on num_genes is for the ++ fitness and child id */ ++ pt->debug_size = num_children * (num_genes + 2) * GENETIC_NUM_DEBUG_POINTS; ++ ++ pt->debug_history = (long long *) kmalloc(pt->debug_size * sizeof(long long), GFP_KERNEL); ++ ++#ifdef CONFIG_PROC_FS ++ entry = create_proc_entry(name, 0644, genetic->debug_dir); ++ ++ if (entry) { ++ entry->nlink = 1; ++ entry->data = pt; ++ entry->read_proc = genetic_debug_read_proc; ++ } ++ ++#endif /* CONFIG_PROC_FS */ ++#endif /* GENETIC_DEBUG */ ++ ++ ++ list_add_tail(&pt->phenotype, &genetic->phenotype); ++ ++ return 0; ++} ++ ++void __init genetic_start(genetic_t * genetic) ++{ ++ if (!genetic_lib_enabled) ++ return; ++ ++ genetic_run_child(genetic); ++ printk(KERN_INFO "%ld children started in %s genetic library\n", genetic->num_children, genetic->name); ++} ++ ++ ++ ++/* create some children, it is up to the lib user to come up w/ a good ++ distro of genes for it's children */ ++static int genetic_create_children(phenotype_t * pt) ++{ ++ unsigned long i; ++ genetic_child_t * child; ++ ++ for (i = 0; i < pt->num_children; i++) { ++ pt->child_ranking[i] = (genetic_child_t *)kmalloc(sizeof(genetic_child_t), GFP_KERNEL); ++ if (!pt->child_ranking[i]) { ++ printk(KERN_ERR "genetic_create_child: not enough memory\n"); ++ for (i = i - 1; i >= 0; i--) ++ kfree(pt->child_ranking[i]); ++ ++ return -ENOMEM; ++ } ++ ++ child = pt->child_ranking[i]; ++ ++ child->id = i; ++ ++ pt->ops->create_child(child); ++ ++ list_add_tail(&child->list, pt->run_queue); ++ } ++ ++ return 0; ++} ++ ++/* See how well child did and run the next one */ ++void genetic_switch_child(unsigned long data) ++{ ++ genetic_t * genetic = (genetic_t *)data; ++ genetic_child_t * child; ++ ++ struct list_head * p; ++ phenotype_t * pt; ++ ++ int new_generation = 0; ++ ++ list_for_each(p, &genetic->phenotype) { ++ pt = list_entry(p, phenotype_t, phenotype); ++ ++ child = list_entry(pt->run_queue->next, genetic_child_t, list); ++ ++ list_del(&child->list); ++ ++ list_add_tail(&child->list, pt->finished_queue); ++ ++ if (pt->ops->calc_fitness) ++ pt->ops->calc_fitness(child); ++ ++ pt->child_ranking[pt->child_number++] = child; ++ ++ /* See if need more children */ ++ if (list_empty(pt->run_queue)) ++ new_generation = 1; ++ } ++ ++ genetic->child_number++; ++ ++ if (new_generation) ++ genetic_new_generation(genetic); ++ ++ genetic_run_child(genetic); ++ ++} ++ ++/* Set the childs genes for run */ ++void genetic_run_child(genetic_t * genetic) ++{ ++ struct list_head * p; ++ phenotype_t * pt; ++ ++ genetic_child_t * child; ++ void * genes; ++ ++ list_for_each(p, &genetic->phenotype) { ++ pt = list_entry(p, phenotype_t, phenotype); ++ ++ child = list_entry(pt->run_queue->next, genetic_child_t, list); ++ ++ genes = child->genes; ++ ++ if (pt->ops->set_child_genes) ++ pt->ops->set_child_genes(genes); ++ ++ if (pt->ops->take_snapshot) ++ pt->ops->take_snapshot(pt); ++ } ++ ++ /* set a timer interrupt */ ++ genetic->timer.expires = jiffies + genetic->child_life_time; ++ add_timer(&genetic->timer); ++ ++} ++ ++/* This natural selection routine will take the top ++ * natural_select_cutoff and use them to make children for the next ++ * generation and keep the top half perfomers ++ * ++ * This assumes natural_select_cutoff is exactly half of num_children ++ * and num_children is a multable of 4. ++ */ ++static void genetic_ns_top_parents(phenotype_t * pt) ++{ ++ unsigned long i,j,k = 0; ++ unsigned long num_children = pt->num_children; ++ unsigned long cutoff = num_children - pt->natural_selection_cutoff; ++ ++ for (i = cutoff, j = num_children - 1; i < j; i++, j--, k += 2) { ++ /* create child A */ ++ pt->ops->combine_genes(pt->child_ranking[i], ++ pt->child_ranking[j], ++ pt->child_ranking[k]); ++ ++ /* create child B */ ++ pt->ops->combine_genes(pt->child_ranking[i], ++ pt->child_ranking[j], ++ pt->child_ranking[k+1]); ++ } ++} ++ ++/* This natural selection routine just has top parents populating ++ bottom performers. */ ++static void genetic_ns_award_top_parents(phenotype_t * pt) ++{ ++ unsigned long i; ++ unsigned long num_children = pt->num_children; ++ unsigned long cutoff = num_children - pt->natural_selection_cutoff; ++ ++ for (i = 0; i < cutoff; i += 2) { ++ pt->ops->combine_genes(pt->child_ranking[num_children - 1], ++ pt->child_ranking[num_children - 2], ++ pt->child_ranking[i]); ++ ++ pt->ops->combine_genes(pt->child_ranking[num_children - 1], ++ pt->child_ranking[num_children - 2], ++ pt->child_ranking[i+1]); ++ } ++} ++ ++static inline void genetic_swap(genetic_child_t ** a, genetic_child_t ** b) ++{ ++ genetic_child_t * tmp = *a; ++ ++ *a = *b; ++ *b = tmp; ++} ++ ++/* bubble sort */ ++/* XXX change this to quick sort */ ++static void genetic_split_performers(phenotype_t * pt) ++{ ++ int i, j; ++ ++ for (i = pt->num_children; i > 1; i--) ++ for (j = 0; j < i - 1; j++) ++ if (pt->child_ranking[j]->fitness > pt->child_ranking[j+1]->fitness) ++ genetic_swap(&pt->child_ranking[j], &pt->child_ranking[j+1]); ++} ++ ++static void genetic_mutate(phenotype_t * pt) ++{ ++ long child_entry = -1; ++ int i; ++ ++ if (!pt->num_genes) ++ return; ++ ++ for (i = 0; i < pt->num_mutations; i++) { ++ get_random_bytes(&child_entry, sizeof(child_entry)); ++ child_entry = child_entry % pt->num_children; ++ ++ pt->ops->mutate_child(pt->child_ranking[child_entry]); ++ } ++} ++ ++/* XXX This will either aid in handling new workloads, or send us on a ++ downward spiral */ ++static void genetic_shift_mutation_rate(phenotype_t * pt, long long prev_gen_avg_fitness, long long avg_fitness) ++{ ++ ++ long low_bound; ++ long high_bound; ++ long dummy; ++ ++ if (mutation_rate_change && pt->genetic->generation_number > 1) { ++ ++ if (pt->ops->shift_mutation_rate) { ++ pt->ops->shift_mutation_rate(pt); ++ } else { ++ ++ low_bound = avg_fitness * 90; ++ divll(&low_bound, 100, &dummy); ++ ++ high_bound = avg_fitness * 110; ++ divll(&high_bound, 100, &dummy); ++ ++ if (high_bound > prev_gen_avg_fitness) ++ pt->mutation_rate -= mutation_rate_change; ++ else if (low_bound < prev_gen_avg_fitness) ++ pt->mutation_rate += mutation_rate_change; ++ ++ if (pt->mutation_rate > GENETIC_MAX_MUTATION_RATE) ++ pt->mutation_rate = GENETIC_MAX_MUTATION_RATE; ++ else if (pt->mutation_rate < GENETIC_MIN_MUTATION_RATE) ++ pt->mutation_rate = GENETIC_MIN_MUTATION_RATE; ++ } ++ } ++} ++ ++void genetic_general_shift_mutation_rate(phenotype_t * in_pt) ++{ ++ struct list_head * p; ++ phenotype_t * pt; ++ int count = 0; ++ long rate = 0; ++ ++ list_for_each(p, &in_pt->genetic->phenotype) { ++ pt = list_entry(p, phenotype_t, phenotype); ++ ++ if (in_pt->uid & pt->uid && in_pt->uid != pt->uid) { ++ rate += pt->mutation_rate; ++ count++; ++ } ++ } ++ ++ /* If we are a general phenotype that is made up of other ++ phenotypes then we take the average */ ++ if (count) ++ in_pt->mutation_rate = (rate / count); ++ else ++ in_pt->mutation_rate = mutation_rate_change; ++} ++ ++static void genetic_calc_stats(phenotype_t * pt) ++{ ++ long long total_fitness = 0; ++ long long prev_gen_avg_fitness = pt->last_gen_avg_fitness; ++ long long tmp_fitness; ++ long dummy; ++ int i; ++ ++ /* calculate the avg fitness for this generation and avg fitness ++ * so far */ ++ for (i = 0; i < pt->num_children; i++) ++ total_fitness += pt->child_ranking[i]->fitness; ++ ++ pt->last_gen_avg_fitness = total_fitness >> long_log2(pt->num_children); ++ ++ /* Mutation rate calibration */ ++ genetic_shift_mutation_rate(pt, prev_gen_avg_fitness, pt->last_gen_avg_fitness); ++ ++ pt->num_mutations = ((pt->num_children * pt->num_genes) * pt->mutation_rate) / 100; ++ ++ /* calc new avg fitness */ ++ tmp_fitness = pt->last_gen_avg_fitness - pt->avg_fitness; ++ divll(&tmp_fitness, pt->genetic->generation_number, &dummy); ++ pt->avg_fitness += tmp_fitness; ++ ++ pt->fitness_history[pt->fitness_history_index++ & GENETIC_HISTORY_MASK] = ++ pt->last_gen_avg_fitness; ++ ++} ++ ++#if GENETIC_DEBUG ++/* Stores attributes into an array in the following format ++ * child_num fitness gene[0] gene[1] .... gene[num_genes-1] ++ * Add +1 to GENETIC_NUM_DEBUG_POINTS if add another dump_children ++ * call ++ */ ++void dump_children(phenotype_t * pt) ++{ ++ int i, j; ++ long * genes; ++ unsigned long debug_size = pt->debug_size; ++ ++ for (i = 0; i < pt->num_children; i++) { ++ pt->debug_history[pt->debug_index++ % debug_size] = pt->child_ranking[i]->id; ++ pt->debug_history[pt->debug_index++ % debug_size] = pt->child_ranking[i]->fitness; ++ ++ genes = (long *)pt->child_ranking[i]->genes; ++ ++ for (j = 0; j < pt->child_ranking[i]->num_genes; j++) { ++ pt->debug_history[pt->debug_index++ % debug_size] = genes[j]; ++ } ++ } ++} ++#else ++void dump_children(genetic_t * genetic) { return; } ++#endif ++ ++void genetic_new_generation(genetic_t * genetic) ++{ ++ struct list_head * tmp; ++ ++ struct list_head * p; ++ phenotype_t * pt; ++ ++ list_for_each(p, &genetic->phenotype) { ++ pt = list_entry(p, phenotype_t, phenotype); ++ ++ /* Check to see if need to recalibrate fitness to take ++ other phenotypes' rankings into account. This ++ should be ran after all phenotypes that have input ++ have been ran. */ ++ if (pt->ops->calc_post_fitness) ++ pt->ops->calc_post_fitness(pt); ++ ++ dump_children(pt); ++ ++ /* figure out top performers */ ++ genetic_split_performers(pt); ++ ++ /* calc stats */ ++ genetic_calc_stats(pt); ++ ++ dump_children(pt); ++ ++ /* make some new children */ ++ if (pt->num_genes) ++ pt->natural_selection(pt); ++ ++ dump_children(pt); ++ ++ /* mutate a couple of the next generation */ ++ genetic_mutate(pt); ++ ++ dump_children(pt); ++ ++ /* Move the new children still sitting in the finished queue to ++ the run queue */ ++ tmp = pt->run_queue; ++ pt->run_queue = pt->finished_queue; ++ pt->finished_queue = tmp; ++ ++ pt->child_number = 0; ++ pt->debug_index = 0; ++ ++ } ++ ++ genetic->child_number = 0; ++ genetic->generation_number++; ++ ++} ++ ++/* Mutate a gene picking a random value within the gene range */ ++void genetic_generic_random_mutate_gene(genetic_child_t * child, long gene_num) ++{ ++ unsigned long *genes = (unsigned long *)child->genes; ++ unsigned long min = child->gene_param[gene_num].min; ++ unsigned long max = child->gene_param[gene_num].max; ++ unsigned long gene_value; ++ unsigned long range = max - min + 1; ++ ++ /* create a mutation value */ ++ get_random_bytes(&gene_value, sizeof(gene_value)); ++ ++ gene_value = gene_value % range; ++ ++ genes[gene_num] = min + gene_value; ++} ++ ++void genetic_generic_iterative_mutate_gene(genetic_child_t * child, long gene_num) ++{ ++ unsigned long *genes = (unsigned long *)child->genes; ++ long min = child->gene_param[gene_num].min; ++ long max = child->gene_param[gene_num].max; ++ long change; ++ long old_value = genes[gene_num]; ++ long new_value; ++ unsigned long range = max - min + 1; ++ ++ /* If under 5, random might work better */ ++ if (range < 5) ++ return genetic_generic_random_mutate_gene(child, gene_num); ++ ++ /* get the % of change */ ++ get_random_bytes(&change, sizeof(change)); ++ ++ change = change % GENETIC_ITERATIVE_MUTATION_RANGE; ++ ++ new_value = ((long)(change * range) / (long)100) + old_value; ++ ++ if (new_value > max) ++ new_value = max; ++ else if (new_value < min) ++ new_value = min; ++ ++ genes[gene_num] = new_value; ++} ++ ++void genetic_iterative_from_default_mutate_gene(genetic_child_t * child, long gene_num) ++{ ++ unsigned long *genes = (unsigned long *)child->genes; ++ long min = child->gene_param[gene_num].min; ++ long max = child->gene_param[gene_num].max; ++ long initial = child->gene_param[gene_num].initial; ++ long change; ++ long old_value = genes[gene_num]; ++ long new_value; ++ unsigned long range = initial - min + 1; ++ ++ /* If under 5, random might work better */ ++ if (range < 5) ++ return genetic_generic_random_mutate_gene(child, gene_num); ++ ++ /* get the % of change */ ++ get_random_bytes(&change, sizeof(change)); ++ ++ change = change % GENETIC_ITERATIVE_MUTATION_RANGE; ++ ++ new_value = ((long)(change * range) / (long)100) + old_value; ++ ++ if (new_value > max) ++ new_value = max; ++ else if (new_value < min) ++ new_value = min; ++ ++ genes[gene_num] = new_value; ++} ++ ++/* This assumes that all genes are a unsigned long array of size ++ num_genes */ ++void genetic_generic_mutate_child(genetic_child_t * child) ++{ ++ long gene_num = -1; ++ ++ /* pick a random gene */ ++ get_random_bytes(&gene_num, sizeof(gene_num)); ++ ++ if (gene_num < 0) ++ gene_num = -gene_num; ++ ++ gene_num = gene_num % child->num_genes; ++ ++ if (child->gene_param[gene_num].mutate_gene) ++ child->gene_param[gene_num].mutate_gene(child, gene_num); ++ else ++ genetic_generic_random_mutate_gene(child, gene_num); ++} ++ ++void genetic_create_child_defaults(genetic_child_t * child) ++{ ++ int i; ++ unsigned long * genes = child->genes; ++ ++ for (i = 0; i < child->num_genes; i++) { ++ genes[i] = child->gene_param[i].initial; ++ } ++} ++ ++void genetic_create_child_spread(genetic_child_t * child, unsigned long num_children) ++{ ++ int i; ++ unsigned long range; ++ int range_incr; ++ int child_num = child->id; ++ long num_genes = child->num_genes; ++ unsigned long * genes = child->genes; ++ ++ for (i = 0; i < num_genes; i++) { ++ range = child->gene_param[i].max - child->gene_param[i].min + 1; ++ range_incr = range / num_children; ++ if (range_incr) ++ genes[i] = child->gene_param[i].min + ++ (range_incr * child_num); ++ else ++ genes[i] = child->gene_param[i].min + ++ (child_num / (num_children / range)); ++ } ++ ++} ++ ++#if 0 ++/* Randomly pick which parent to use for each gene to create a child */ ++void genetic_generic_combine_genes(genetic_child_t * parent_a, ++ genetic_child_t * parent_b, ++ genetic_child_t * child) ++{ ++ unsigned long * genes_a = (unsigned long *)parent_a->genes; ++ unsigned long * genes_b = (unsigned long *)parent_b->genes; ++ unsigned long * child_genes = (unsigned long *)child->genes; ++ ++ /* Assume parent_a and parent_b have same num_genes */ ++ unsigned long num_genes = parent_a->num_genes; ++ int parent_selector; ++ int i; ++ ++ get_random_bytes(&parent_selector, sizeof(parent_selector)); ++ ++ if ((sizeof(parent_selector) * 8) < num_genes) ++ BUG(); ++ ++ for (i = 0; i < num_genes; i++) { ++ /* Look at each bit to determine which parent to use */ ++ if (parent_selector & 1) { ++ child_genes[i] = genes_a[i]; ++ } else { ++ child_genes[i] = genes_b[i]; ++ } ++ parent_selector >>= 1; ++ } ++} ++#else ++ ++/* Randomly pick a percentage of each parent to use for each gene to create a child */ ++void genetic_generic_combine_genes(genetic_child_t * parent_a, ++ genetic_child_t * parent_b, ++ genetic_child_t * child) ++{ ++ unsigned long * genes_a = (unsigned long *)parent_a->genes; ++ unsigned long * genes_b = (unsigned long *)parent_b->genes; ++ unsigned long * child_genes = (unsigned long *)child->genes; ++ ++ /* Assume parent_a and parent_b have same num_genes */ ++ unsigned long num_genes = parent_a->num_genes; ++ int percentage; ++ int i; ++ ++ for (i = 0; i < num_genes; i++) { ++ get_random_bytes(&percentage, sizeof(percentage)); ++ ++ /* Get percentage */ ++ percentage = percentage % 100; ++ ++ if (percentage < 0) ++ percentage = -percentage; ++ ++ /* Give child x% of parent A's genes value, plus ++ 100-x% of parent B's genes value */ ++ child_genes[i] = (((genes_a[i]+1) * percentage) + ++ (genes_b[i] * (100 - percentage))) / 100; ++ } ++} ++#endif ++ ++static int __init genetic_boot_setup(char *str) ++{ ++ if (strcmp(str, "on") == 0) ++ genetic_lib_enabled = 1; ++ else if (strcmp(str, "off") == 0) ++ genetic_lib_enabled = 0; ++ ++ return 1; ++} ++ ++ ++static int __init genetic_mutation_rate_change_setup(char *str) ++{ ++ int i; ++ ++ if (get_option(&str,&i)) { ++ ++ if (i > GENETIC_MAX_MUTATION_RATE) ++ i = GENETIC_MAX_MUTATION_RATE; ++ else if (i < 0) ++ i = 0; ++ ++ mutation_rate_change = i; ++ } ++ ++ return 1; ++ ++} ++__setup("genetic=", genetic_boot_setup); ++__setup("genetic_mutate_rate=", genetic_mutation_rate_change_setup); diff --git a/genetic-zaphod-cpu-sched-2.6.11-gl1.patch b/genetic-zaphod-cpu-sched-2.6.11-gl1.patch new file mode 100644 index 0000000..8a95abe --- /dev/null +++ b/genetic-zaphod-cpu-sched-2.6.11-gl1.patch @@ -0,0 +1,820 @@ +Index: 2.6.11/include/linux/sched.h +=================================================================== +--- 2.6.11.orig/include/linux/sched.h 2005-04-15 10:53:39.650077696 -0500 ++++ 2.6.11/include/linux/sched.h 2005-04-15 10:58:45.638199368 -0500 +@@ -142,6 +142,19 @@ + #include + + /* ++ * These are the 'tuning knobs' of the scheduler: ++ * ++ * Default configurable timeslice is 100 msecs, maximum configurable ++ * timeslice is 1000 msecs and minumum configurable timeslice is 1 jiffy. ++ * Timeslices get renewed on task creation, on wake up and after they expire. ++ */ ++#define MIN_TIMESLICE 1 ++#define DEF_TIMESLICE (100 * HZ / 1000) ++#define MAX_TIMESLICE (1000 * HZ / 1000) ++ ++#define DEFAULT_UNPRIV_RT_THRESHOLD 10 ++ ++/* + * This serializes "schedule()" and also protects + * the run-queue from deletions/modifications (but + * _adding_ to the beginning of the run-queue has +@@ -557,6 +570,7 @@ + unsigned long policy; + cpumask_t cpus_allowed; + unsigned long time_slice; ++ unsigned long time_slice_ran; + + #ifdef CONFIG_SCHEDSTATS + struct sched_info sched_info; +@@ -822,6 +836,8 @@ + extern int sched_setscheduler(struct task_struct *, int, struct sched_param *); + extern task_t *idle_task(int cpu); + ++extern void genetic_cpu_sched_init(void); ++ + void yield(void); + + /* +@@ -1200,9 +1216,62 @@ + } + #endif + ++enum zaphod_mode_enum { ++ ZAPHOD_MODE_PRIORITY_BASED, ++ ZAPHOD_MODE_ENTITLEMENT_BASED ++}; ++ ++#ifdef CONFIG_GENETIC_ZAPHOD_CPU_SCHED + extern long sched_setaffinity(pid_t pid, cpumask_t new_mask); + extern long sched_getaffinity(pid_t pid, cpumask_t *mask); + ++ ++#define ZAPHOD_SCHED_NUM_GENES 9 ++#define ZAPHOD_SCHED_NUM_CHILDREN 8 ++//#define ZAPHOD_SCHED_CHILD_LIFESPAN (9 * (HZ / 2)) ++#define ZAPHOD_SCHED_CHILD_LIFESPAN (4 * HZ) ++//#define ZAPHOD_SCHED_CHILD_LIFESPAN (6 * HZ) ++ ++struct zaphod_rt_genes { ++ unsigned long sched_rr_time_slice; ++}; ++struct zaphod_intr_genes { ++ unsigned long ia_threshold; ++ unsigned long cpu_hog_threshold; ++}; ++ ++struct zaphod_fork_genes { ++ unsigned long initial_ia_bonus; ++}; ++ ++struct zaphod_general_genes { ++ unsigned long time_slice; ++ unsigned long max_ia_bonus; ++ unsigned long max_tpt_bonus; ++ unsigned long bgnd_time_slice_multiplier; ++ unsigned long zaphod_mode; ++}; ++ ++struct zaphod_stats_snapshot { ++ /* from struct runq_cpustats */ ++ unsigned long long total_delay; ++ unsigned long long total_rt_delay; ++ unsigned long long total_intr_delay; ++ unsigned long long total_rt_intr_delay; ++ unsigned long long total_fork_delay; ++ ++ /* from struct cpu_cpustats */ ++ unsigned long long nr_switches; ++ ++#ifdef CONFIG_SCHEDSTATS ++ /* from sched_info */ ++ unsigned long cpu_time; ++ unsigned long run_delay; ++#endif ++}; ++ ++#endif /* CONFIG_GENETIC_ZAPHOD_CPU_SCHED */ ++ + #ifdef CONFIG_MAGIC_SYSRQ + + extern void normalize_rt_tasks(void); +Index: 2.6.11/kernel/sched.c +=================================================================== +--- 2.6.11.orig/kernel/sched.c 2005-04-15 10:53:39.659081044 -0500 ++++ 2.6.11/kernel/sched.c 2005-04-15 10:58:45.642200856 -0500 +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -59,25 +60,13 @@ + #define TASK_NICE(p) PRIO_TO_NICE((p)->static_prio) + + /* +- * These are the 'tuning knobs' of the scheduler: +- * +- * Default configurable timeslice is 100 msecs, maximum configurable +- * timeslice is 1000 msecs and minumum configurable timeslice is 1 jiffy. +- * Timeslices get renewed on task creation, on wake up and after they expire. +- */ +-#define MIN_TIMESLICE 1 +-#define DEF_TIMESLICE (100 * HZ / 1000) +-#define MAX_TIMESLICE (1000 * HZ / 1000) +- +-/* + * UNPRIV_RT tasks that have a CPU usage rate less than this threshold + * (in parts per thousand) are treated as psuedo RT tasks + */ +-#define DEFAULT_UNPRIV_RT_THRESHOLD 10 + unsigned long unpriv_rt_threshold = PROP_FM_PPT(DEFAULT_UNPRIV_RT_THRESHOLD); + + unsigned long time_slice = DEF_TIMESLICE; +-static unsigned long sched_rr_time_slice = (100 * HZ / 1000); ++unsigned long sched_rr_time_slice = (100 * HZ / 1000); + + /* + * Background tasks may have longer time slices as compensation +@@ -116,6 +105,11 @@ + struct list_head queue; + }; + ++#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu))) ++#define this_rq() (&__get_cpu_var(runqueues)) ++#define task_rq(p) ((p)->rq) ++#define cpu_curr(cpu) (cpu_rq(cpu)->curr) ++ + /* + * This is the main, per-CPU runqueue data structure. + * +@@ -211,11 +205,6 @@ + #define for_each_domain(cpu, domain) \ + for (domain = cpu_rq(cpu)->sd; domain; domain = domain->parent) + +-#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu))) +-#define this_rq() (&__get_cpu_var(runqueues)) +-#define task_rq(p) ((p)->rq) +-#define cpu_curr(cpu) (cpu_rq(cpu)->curr) +- + #ifdef CONFIG_SMP + void fastcall set_task_cpu(struct task_struct *p, unsigned int cpu) + { +@@ -670,6 +659,7 @@ + recalc_task_prio(p, now); + + p->time_slice = task_timeslice(p); ++ p->time_slice_ran = 0; + p->flags &= ~PF_UISLEEP; + __activate_task(p); + } +@@ -1156,6 +1146,7 @@ + * Give the task a new timeslice. + */ + p->time_slice = task_timeslice(p); ++ p->time_slice_ran = 0; + now = sched_clock(); + local_irq_enable(); + /* +@@ -1222,7 +1213,7 @@ + * No more timeslice fiddling on exit + * (Optionally) log scheduler statistics at exit. + */ +-static int log_at_exit = 0; ++int log_at_exit = 0; + void fastcall sched_exit(task_t * p) + { + struct task_cpustats stats; +@@ -2167,6 +2158,19 @@ + } + } + ++#ifdef CONFIG_GENETIC_ZAPHOD_CPU_SCHED ++static inline void genetic_fixup_timeslice(task_t * p) ++{ ++ unsigned long tmp_timeslice = task_timeslice(p); ++ ++ if (p->time_slice > tmp_timeslice) ++ p->time_slice = tmp_timeslice; ++ ++ if (++p->time_slice_ran > tmp_timeslice) ++ p->time_slice = 1; ++} ++#endif ++ + /* + * Do the virtual profiling signal calculations. + * @p: the process that the cpu time gets accounted to +@@ -2324,6 +2328,10 @@ + goto out; + + spin_lock(&rq->lock); ++ ++#ifdef CONFIG_GENETIC_ZAPHOD_CPU_SCHED ++ genetic_fixup_timeslice(p); ++#endif + /* + * The task was running during this tick + */ +@@ -2338,6 +2346,7 @@ + p->prio = effective_prio(p); + p->time_slice = task_timeslice(p); + } ++ p->time_slice_ran = 0; + enqueue_task(p); + } + spin_unlock(&rq->lock); +@@ -5173,3 +5182,174 @@ + { .ctl_name = CPU_SCHED_END_OF_LIST } + }; + #endif ++ ++#ifdef CONFIG_GENETIC_ZAPHOD_CPU_SCHED ++ ++extern unsigned int max_ia_bonus; ++extern unsigned long ia_threshold; ++extern unsigned long cpu_hog_threshold; ++extern unsigned int initial_ia_bonus; ++extern unsigned int max_tpt_bonus; ++extern enum zaphod_mode_enum zaphod_mode; ++ ++void zaphod_rt_set_child_genes(void * in_genes) ++{ ++ struct zaphod_rt_genes * genes = (struct zaphod_rt_genes *)in_genes; ++ ++ sched_rr_time_slice = genes->sched_rr_time_slice; ++} ++ ++void zaphod_intr_set_child_genes(void * in_genes) ++{ ++ struct zaphod_intr_genes * genes = (struct zaphod_intr_genes *)in_genes; ++ ++ ia_threshold = ppt_to_proportion(genes->ia_threshold); ++ cpu_hog_threshold = ppt_to_proportion(genes->cpu_hog_threshold); ++} ++ ++void zaphod_fork_set_child_genes(void * in_genes) ++{ ++ struct zaphod_fork_genes * genes = (struct zaphod_fork_genes *)in_genes; ++ ++ initial_ia_bonus = genes->initial_ia_bonus; ++} ++ ++void zaphod_general_set_child_genes(void * in_genes) ++{ ++ struct zaphod_general_genes * genes = (struct zaphod_general_genes *)in_genes; ++ ++ time_slice = genes->time_slice; ++ base_prom_interval = ((time_slice * 15) / 10); ++ max_ia_bonus = genes->max_ia_bonus; ++ max_tpt_bonus = genes->max_tpt_bonus; ++ bgnd_time_slice_multiplier = genes->bgnd_time_slice_multiplier; ++ zaphod_mode = genes->zaphod_mode; ++ ++} ++ ++/* Just have the general phenotype take the whole snapshot */ ++void zaphod_general_take_snapshot(phenotype_t * pt) ++{ ++ struct runq_cpustats * csrq; ++ struct zaphod_stats_snapshot * ss = (struct zaphod_stats_snapshot *)pt->child_ranking[0]->stats_snapshot; ++#ifdef CONFIG_SCHEDSTATS ++ runqueue_t * rq; ++#endif ++ int cpu; ++ ++ memset(ss, 0, sizeof(struct zaphod_stats_snapshot)); ++ ++ /* Get snapshot for this child */ ++ for_each_online_cpu(cpu) { ++ csrq = cpu_runq_cpustats(cpu); ++ ++ ss->total_delay += csrq->total_delay; ++ ss->total_rt_delay += csrq->total_rt_delay; ++ ss->total_intr_delay += csrq->total_intr_delay; ++ ss->total_rt_intr_delay += csrq->total_rt_intr_delay; ++ ss->total_fork_delay += csrq->total_fork_delay; ++ ++ } ++ ++#ifdef CONFIG_SCHEDSTATS ++ for_each_online_cpu(cpu) { ++ rq = cpu_rq(cpu); ++ ++ ss->cpu_time += rq->rq_sched_info.cpu_time; ++ ss->run_delay += rq->rq_sched_info.run_delay; ++ } ++#endif ++ ++ ss->nr_switches += nr_context_switches(); ++ ++ ++ ++} ++ ++void zaphod_rt_calc_fitness(genetic_child_t * child) ++{ ++ ++ struct zaphod_stats_snapshot * ss = (struct zaphod_stats_snapshot *)child->stats_snapshot; ++ struct runq_cpustats *csrq; ++ long long total_rt_delay = 0; ++ int cpu; ++ ++ for_each_online_cpu(cpu) { ++ csrq = cpu_runq_cpustats(cpu); ++ ++ total_rt_delay += csrq->total_rt_delay; ++ } ++ child->fitness = -(total_rt_delay - ss->total_rt_delay); ++ ++} ++ ++void zaphod_intr_calc_fitness(genetic_child_t * child) ++{ ++ struct zaphod_stats_snapshot * ss = (struct zaphod_stats_snapshot *)child->stats_snapshot; ++ struct runq_cpustats *csrq; ++ long long total_intr_delay = 0; ++ int cpu; ++ ++ for_each_online_cpu(cpu) { ++ csrq = cpu_runq_cpustats(cpu); ++ ++ total_intr_delay += csrq->total_intr_delay; ++ } ++ child->fitness = -(total_intr_delay - ss->total_intr_delay); ++ ++} ++ ++void zaphod_fork_calc_fitness(genetic_child_t * child) ++{ ++ struct zaphod_stats_snapshot * ss = (struct zaphod_stats_snapshot *)child->stats_snapshot; ++ struct runq_cpustats *csrq; ++ long long total_fork_delay = 0; ++ int cpu; ++ ++ for_each_online_cpu(cpu) { ++ csrq = cpu_runq_cpustats(cpu); ++ ++ total_fork_delay += csrq->total_fork_delay; ++ } ++ child->fitness = -(total_fork_delay - ss->total_fork_delay); ++ ++} ++ ++void zaphod_total_delay_calc_fitness(genetic_child_t * child) ++{ ++ struct zaphod_stats_snapshot * ss = (struct zaphod_stats_snapshot *)child->stats_snapshot; ++ struct runq_cpustats *csrq; ++ long long total_delay = 0; ++ long long total_rt_delay = 0; ++ long long total_intr_delay = 0; ++ long long total_rt_intr_delay = 0; ++ int cpu; ++ ++ for_each_online_cpu(cpu) { ++ csrq = cpu_runq_cpustats(cpu); ++ ++ total_delay += csrq->total_delay; ++ total_intr_delay += csrq->total_intr_delay; ++ total_rt_delay += csrq->total_rt_delay; ++ total_rt_intr_delay += csrq->total_rt_intr_delay; ++ } ++ ++ /* get delta */ ++ total_delay -= ss->total_delay; ++ total_rt_delay -= ss->total_rt_delay; ++ total_intr_delay -= ss->total_intr_delay; ++ total_rt_intr_delay -= ss->total_rt_intr_delay; ++ ++ child->fitness = -(total_delay - total_rt_delay - (total_intr_delay - total_rt_intr_delay)); ++ ++} ++ ++void zaphod_context_switches_calc_fitness(genetic_child_t * child) ++{ ++ struct zaphod_stats_snapshot * ss = (struct zaphod_stats_snapshot *)child->stats_snapshot; ++ ++ child->fitness = -(nr_context_switches() - ss->nr_switches); ++} ++ ++#endif /* CONFIG_GENETIC_ZAPHOD_CPU_SCHED */ ++ +Index: 2.6.11/kernel/sched_zaphod.c +=================================================================== +--- 2.6.11.orig/kernel/sched_zaphod.c 2005-04-15 10:53:39.661081788 -0500 ++++ 2.6.11/kernel/sched_zaphod.c 2005-04-15 10:58:45.643201228 -0500 +@@ -21,9 +21,13 @@ + */ + #include + #include ++#include ++#include + + #include + ++enum zaphod_mode_enum zaphod_mode = ZAPHOD_MODE_PRIORITY_BASED; ++ + #ifdef CONFIG_CPUSCHED_ZAPHOD + #define MAX_PRIO ZAPHOD_MAX_PRIO + #define MIN_NORMAL_PRIO ZAPHOD_MIN_NORMAL_PRIO +@@ -42,13 +46,6 @@ + + #define EB_YARDSTICK_DECAY_INTERVAL 100 + +-enum zaphod_mode_enum { +- ZAPHOD_MODE_PRIORITY_BASED, +- ZAPHOD_MODE_ENTITLEMENT_BASED +-}; +- +-static enum zaphod_mode_enum zaphod_mode = ZAPHOD_MODE_PRIORITY_BASED; +- + #ifdef CONFIG_SYSCTL + static const char *zaphod_mode_names[] = { + "pb", /* ZAPHOD_MODE_PRIORITY_BASED */ +@@ -446,6 +443,353 @@ + calculate_pre_bonus_priority(p); + } + ++#ifdef CONFIG_GENETIC_ZAPHOD_CPU_SCHED ++ ++extern unsigned long sched_rr_time_slice; ++extern unsigned long base_prom_interval; ++static void zaphod_rt_create_child(genetic_child_t *); ++static void zaphod_intr_create_child(genetic_child_t *); ++static void zaphod_fork_create_child(genetic_child_t *); ++static void zaphod_total_delay_create_child(genetic_child_t *); ++static void zaphod_context_switches_create_child(genetic_child_t *); ++static void zaphod_general_create_child(genetic_child_t *); ++static void zaphod_shift_mutation_rate(phenotype_t * in_pt); ++ ++void zaphod_rt_set_child_genes(void *); ++void zaphod_intr_set_child_genes(void *); ++void zaphod_fork_set_child_genes(void *); ++void zaphod_general_set_child_genes(void *); ++ ++void zaphod_rt_calc_fitness(genetic_child_t *); ++void zaphod_intr_calc_fitness(genetic_child_t *); ++void zaphod_fork_calc_fitness(genetic_child_t *); ++void zaphod_total_delay_calc_fitness(genetic_child_t *); ++void zaphod_context_switches_calc_fitness(genetic_child_t *); ++ ++void zaphod_general_calc_post_fitness(phenotype_t *); ++ ++void zaphod_general_take_snapshot(phenotype_t *); ++ ++/* For real-time tasks */ ++struct genetic_ops zaphod_rt_genetic_ops = { ++ .create_child = zaphod_rt_create_child, ++ .set_child_genes = zaphod_rt_set_child_genes, ++ .calc_fitness = zaphod_rt_calc_fitness, ++ .combine_genes = genetic_generic_combine_genes, ++ .mutate_child = genetic_generic_mutate_child, ++}; ++ ++/* For interactivity */ ++struct genetic_ops zaphod_intr_genetic_ops = { ++ .create_child = zaphod_intr_create_child, ++ .set_child_genes = zaphod_intr_set_child_genes, ++ .calc_fitness = zaphod_intr_calc_fitness, ++ .combine_genes = genetic_generic_combine_genes, ++ .mutate_child = genetic_generic_mutate_child, ++}; ++ ++/* For new processes */ ++struct genetic_ops zaphod_fork_genetic_ops = { ++ .create_child = zaphod_fork_create_child, ++ .set_child_genes = zaphod_fork_set_child_genes, ++ .calc_fitness = zaphod_fork_calc_fitness, ++ .combine_genes = genetic_generic_combine_genes, ++ .mutate_child = genetic_generic_mutate_child, ++}; ++ ++/* For total delay */ ++struct genetic_ops zaphod_total_delay_genetic_ops = { ++ .create_child = zaphod_total_delay_create_child, ++ .calc_fitness = zaphod_total_delay_calc_fitness, ++}; ++ ++/* For context switches */ ++struct genetic_ops zaphod_context_switches_genetic_ops = { ++ .create_child = zaphod_context_switches_create_child, ++ .calc_fitness = zaphod_context_switches_calc_fitness, ++}; ++ ++/* For general genes */ ++struct genetic_ops zaphod_general_genetic_ops = { ++ .create_child = zaphod_general_create_child, ++ .set_child_genes = zaphod_general_set_child_genes, ++ .combine_genes = genetic_generic_combine_genes, ++ .mutate_child = genetic_generic_mutate_child, ++ .calc_post_fitness = zaphod_general_calc_post_fitness, ++ .take_snapshot = zaphod_general_take_snapshot, ++ .shift_mutation_rate = zaphod_shift_mutation_rate ++}; ++ ++#define ZAPHOD_RT_UID 1 ++#define ZAPHOD_RT_NUM_GENES 1 ++gene_param_t zaphod_rt_gene_param[ZAPHOD_RT_NUM_GENES] = { ++ { MIN_TIMESLICE, MAX_TIMESLICE, (100 * HZ / 1000), 0 }, /* sched_rr_time_slice */ ++}; ++ ++#define ZAPHOD_INTR_UID 2 ++#define ZAPHOD_INTR_NUM_GENES 2 ++#if 1 ++gene_param_t zaphod_intr_gene_param[ZAPHOD_INTR_NUM_GENES] = { ++ { 0, 1000, DEFAULT_IA_THRESHOLD, genetic_generic_iterative_mutate_gene }, /* ia_threshold */ ++ { 0, 1000, DEFAULT_CPU_HOG_THRESHOLD, genetic_generic_iterative_mutate_gene }, /* cpu_hog_threshold */ ++}; ++#else ++gene_param_t zaphod_intr_gene_param[ZAPHOD_INTR_NUM_GENES] = { ++ { 0, 1000, DEFAULT_IA_THRESHOLD, 0 }, /* ia_threshold */ ++ { 0, 1000, DEFAULT_CPU_HOG_THRESHOLD, 0 }, /* cpu_hog_threshold */ ++}; ++#endif ++ ++#define ZAPHOD_FORK_UID 4 ++#define ZAPHOD_FORK_NUM_GENES 1 ++gene_param_t zaphod_fork_gene_param[ZAPHOD_FORK_NUM_GENES] = { ++ { 0, MAX_MAX_IA_BONUS, 1, 0 }, /* initial_ia_bonus */ ++}; ++ ++#define ZAPHOD_TOTAL_DELAY_UID 8 ++#define ZAPHOD_TOTAL_DELAY_NUM_GENES 0 ++ ++#define ZAPHOD_CONTEXT_SWITCHES_UID 16 ++#define ZAPHOD_CONTEXT_SWITCHES_NUM_GENES 0 ++ ++#define ZAPHOD_GENERAL_UID (ZAPHOD_CONTEXT_SWITCHES_UID | ZAPHOD_TOTAL_DELAY_UID | ZAPHOD_INTR_UID | ZAPHOD_RT_UID) ++#define ZAPHOD_GENERAL_NUM_GENES 5 ++#if 0 ++gene_param_t zaphod_general_gene_param[ZAPHOD_GENERAL_NUM_GENES] = { ++ { MIN_TIMESLICE, MAX_TIMESLICE, DEF_TIMESLICE, genetic_generic_iterative_mutate_gene }, /* time_slice */ ++ { 0, MAX_MAX_IA_BONUS, DEFAULT_MAX_IA_BONUS, 0 }, /* max_ia_bonus */ ++ { 0, MAX_MAX_TPT_BONUS, DEFAULT_MAX_TPT_BONUS, 0 }, /* max_tpt_bonus */ ++ { 1, 100, 1, genetic_generic_iterative_mutate_gene }, /* bgnd_time_slice_multiplier */ ++ { 0, 1, 0, 0 }, /* zaphod_mode */ ++}; ++#else ++gene_param_t zaphod_general_gene_param[ZAPHOD_GENERAL_NUM_GENES] = { ++ { MIN_TIMESLICE, MAX_TIMESLICE, DEF_TIMESLICE, 0 }, /* time_slice */ ++ { 0, MAX_MAX_IA_BONUS, DEFAULT_MAX_IA_BONUS, 0 }, /* max_ia_bonus */ ++ { 0, MAX_MAX_TPT_BONUS, DEFAULT_MAX_TPT_BONUS, 0 }, /* max_tpt_bonus */ ++ { 1, 100, 1, genetic_generic_iterative_mutate_gene }, /* bgnd_time_slice_multiplier */ ++ { 0, 1, 0, 0 }, /* zaphod_mode */ ++}; ++#endif ++ ++struct zaphod_stats_snapshot * zaphod_stats_snapshot; ++ ++static int __init genetic_zaphod_sched_init(void) ++{ ++ genetic_t * genetic = 0; ++ ++ zaphod_stats_snapshot = (struct zaphod_stats_snapshot *)kmalloc(sizeof(struct zaphod_stats_snapshot), GFP_KERNEL); ++ if (!zaphod_stats_snapshot) ++ panic("zaphod sched: failed to malloc enough space"); ++ ++ if(genetic_init(&genetic, ZAPHOD_SCHED_NUM_CHILDREN, ZAPHOD_SCHED_CHILD_LIFESPAN, ++ "zaphod-sched")) ++ panic("zaphod sched: failed to init genetic lib"); ++ ++ if(genetic_register_phenotype(genetic, &zaphod_rt_genetic_ops, ZAPHOD_SCHED_NUM_CHILDREN, ++ "real-time-tasks", ZAPHOD_RT_NUM_GENES, ZAPHOD_RT_UID)) ++ panic("zaphod sched: failed to register real-time tasks phenotype"); ++ ++ if(genetic_register_phenotype(genetic, &zaphod_intr_genetic_ops, ZAPHOD_SCHED_NUM_CHILDREN, ++ "interactiveness", ZAPHOD_INTR_NUM_GENES, ZAPHOD_INTR_UID)) ++ panic("zaphod sched: failed to register interactiveness phenotype"); ++ ++ if(genetic_register_phenotype(genetic, &zaphod_fork_genetic_ops, ZAPHOD_SCHED_NUM_CHILDREN, ++ "initial-interactiveness", ZAPHOD_FORK_NUM_GENES, ZAPHOD_FORK_UID)) ++ panic("zaphod sched: failed to register initial-interactiveness phenotype"); ++ ++ if(genetic_register_phenotype(genetic, &zaphod_total_delay_genetic_ops, ZAPHOD_SCHED_NUM_CHILDREN, ++ "total-delay", ZAPHOD_TOTAL_DELAY_NUM_GENES, ZAPHOD_TOTAL_DELAY_UID)) ++ panic("zaphod sched: failed to register total-delay phenotype"); ++ ++ if(genetic_register_phenotype(genetic, &zaphod_context_switches_genetic_ops, ZAPHOD_SCHED_NUM_CHILDREN, ++ "context-switches", ZAPHOD_CONTEXT_SWITCHES_NUM_GENES, ZAPHOD_CONTEXT_SWITCHES_UID)) ++ panic("zaphod sched: failed to register context-switches phenotype"); ++ ++ if(genetic_register_phenotype(genetic, &zaphod_general_genetic_ops, ZAPHOD_SCHED_NUM_CHILDREN, ++ "general", ZAPHOD_GENERAL_NUM_GENES, ZAPHOD_GENERAL_UID)) ++ panic("zaphod sched: failed to register general phenotype"); ++ ++ genetic_start(genetic); ++ ++ return 0; ++} ++ ++void zaphod_rt_create_child(genetic_child_t * child) ++{ ++ BUG_ON(!child); ++ ++ child->genes = (void *)kmalloc(sizeof(struct zaphod_rt_genes), GFP_KERNEL); ++ if (!child->genes) ++ panic("zaphod_rt_create_child: error kmalloc'n space"); ++ ++ child->gene_param = zaphod_rt_gene_param; ++ child->num_genes = ZAPHOD_RT_NUM_GENES; ++ child->stats_snapshot = zaphod_stats_snapshot; ++ ++// genetic_create_child_spread(child, ZAPHOD_SCHED_NUM_CHILDREN); ++ genetic_create_child_defaults(child); ++ ++} ++ ++void zaphod_intr_create_child(genetic_child_t * child) ++{ ++ BUG_ON(!child); ++ ++ child->genes = (void *)kmalloc(sizeof(struct zaphod_intr_genes), GFP_KERNEL); ++ if (!child->genes) ++ panic("zaphod_intr_create_child: error kmalloc'n space"); ++ ++ child->gene_param = zaphod_intr_gene_param; ++ child->num_genes = ZAPHOD_INTR_NUM_GENES; ++ child->stats_snapshot = zaphod_stats_snapshot; ++ ++// genetic_create_child_spread(child, ZAPHOD_SCHED_NUM_CHILDREN); ++ genetic_create_child_defaults(child); ++} ++ ++void zaphod_fork_create_child(genetic_child_t * child) ++{ ++ BUG_ON(!child); ++ ++ child->genes = (void *)kmalloc(sizeof(struct zaphod_fork_genes), GFP_KERNEL); ++ if (!child->genes) ++ panic("zaphod_fork_create_child: error kmalloc'n space"); ++ ++ child->gene_param = zaphod_fork_gene_param; ++ child->num_genes = ZAPHOD_FORK_NUM_GENES; ++ child->stats_snapshot = zaphod_stats_snapshot; ++ ++// genetic_create_child_spread(child, ZAPHOD_SCHED_NUM_CHILDREN); ++ genetic_create_child_defaults(child); ++} ++ ++void zaphod_total_delay_create_child(genetic_child_t * child) ++{ ++ BUG_ON(!child); ++ ++ child->genes = 0; ++ child->gene_param = 0; ++ child->num_genes = 0; ++ child->stats_snapshot = zaphod_stats_snapshot; ++} ++ ++void zaphod_context_switches_create_child(genetic_child_t * child) ++{ ++ BUG_ON(!child); ++ ++ child->genes = 0; ++ child->gene_param = 0; ++ child->num_genes = 0; ++ child->stats_snapshot = zaphod_stats_snapshot; ++} ++ ++void zaphod_general_create_child(genetic_child_t * child) ++{ ++ BUG_ON(!child); ++ ++ child->genes = (void *)kmalloc(sizeof(struct zaphod_general_genes), GFP_KERNEL); ++ if (!child->genes) ++ panic("zaphod_general_create_child: error kmalloc'n space"); ++ ++ child->gene_param = zaphod_general_gene_param; ++ child->num_genes = ZAPHOD_GENERAL_NUM_GENES; ++ child->stats_snapshot = zaphod_stats_snapshot; ++ ++ genetic_create_child_spread(child, ZAPHOD_SCHED_NUM_CHILDREN); ++// genetic_create_child_defaults(child); ++} ++ ++ ++static void zaphod_shift_mutation_rate(phenotype_t * in_pt) ++{ ++ struct list_head * p; ++ phenotype_t * pt; ++ int count = 0; ++ long rate = 0; ++ ++ list_for_each(p, &in_pt->genetic->phenotype) { ++ pt = list_entry(p, phenotype_t, phenotype); ++ ++ /* Look at everyone else that contributes to this ++ phenotype */ ++ if (pt->uid & ZAPHOD_GENERAL_UID && pt->uid != ZAPHOD_GENERAL_UID) { ++ ++ switch (pt->uid) { ++ case ZAPHOD_RT_UID: ++ break; ++ case ZAPHOD_CONTEXT_SWITCHES_UID: ++ break; ++ case ZAPHOD_INTR_UID: ++ case ZAPHOD_TOTAL_DELAY_UID: ++ rate += pt->mutation_rate; ++ count++; ++ break; ++ default: ++ BUG(); ++ } ++ } ++ } ++ ++ /* If we are a general phenotype that is made up of other ++ phenotypes then we take the average */ ++ if (count) ++ in_pt->mutation_rate = (rate / count); ++ else ++ BUG(); ++} ++ ++ ++/* Make the general the one that takes into account all the fitness ++ * routines, since these are the common genes that effect everything. ++ */ ++void zaphod_general_calc_post_fitness(phenotype_t * in_pt) ++{ ++ struct list_head * p; ++ phenotype_t * pt; ++ genetic_t * genetic = in_pt->genetic; ++ int ranking[ZAPHOD_SCHED_NUM_CHILDREN]; ++ int weight = 1; ++ int i; ++ ++ memset(ranking, 0, sizeof(ranking)); ++ ++ list_for_each(p, &genetic->phenotype) { ++ pt = list_entry(p, phenotype_t, phenotype); ++ ++ /* Look at everyone else that contributes to this ++ phenotype */ ++ if (pt->uid & ZAPHOD_GENERAL_UID && pt->uid != ZAPHOD_GENERAL_UID) { ++ ++ switch (pt->uid) { ++ case ZAPHOD_RT_UID: ++ case ZAPHOD_CONTEXT_SWITCHES_UID: ++ weight = 1; ++ break; ++ case ZAPHOD_INTR_UID: ++ weight = 2; ++ break; ++ case ZAPHOD_TOTAL_DELAY_UID: ++ weight = 3; ++ break; ++ default: ++ BUG(); ++ } ++ ++ for (i = 0; i < pt->num_children; i++) ++ ranking[pt->child_ranking[i]->id] += (i * weight); ++ } ++ } ++ ++ for (i = 0; i < in_pt->num_children; i++) ++ in_pt->child_ranking[i]->fitness = ranking[i]; ++ ++} ++ ++core_initcall(genetic_zaphod_sched_init); ++ ++#endif /* CONFIG_GENETIC_ZAPHOD_CPU_SCHED */ ++ + #if defined(CONFIG_SYSCTL) + static const unsigned int zero = 0; + +@@ -456,6 +800,8 @@ + { + int res; + ++ BUG_ON(zaphod_mode >= 2); ++ + strcpy(current_zaphod_mode, zaphod_mode_names[zaphod_mode]); + res = proc_dostring(ctp, write, fp, buffer, lenp, ppos); + +Index: 2.6.11/lib/Kconfig +=================================================================== +--- 2.6.11.orig/lib/Kconfig 2005-04-15 10:58:26.263606416 -0500 ++++ 2.6.11/lib/Kconfig 2005-04-15 10:58:45.644201600 -0500 +@@ -36,6 +36,14 @@ + This option will build in a genetic library that will tweak + kernel parameters autonomically to improve performance. + ++config GENETIC_ZAPHOD_CPU_SCHED ++ bool "Genetic Library - Zaphod CPU scheduler" ++ depends on GENETIC_LIB && EXPERIMENTAL ++ select SCHEDSTATS ++ help ++ This option will enable the genetic library on the zaphod ++ CPU scheduler. ++ + # + # compression support is select'ed if needed + # diff --git a/ols2005v1-pages-335-346.pdf b/ols2005v1-pages-335-346.pdf new file mode 100644 index 0000000..ba6f32a Binary files /dev/null and b/ols2005v1-pages-335-346.pdf differ diff --git a/zaphod-v6.2.patch b/zaphod-v6.2.patch new file mode 100644 index 0000000..56df23e --- /dev/null +++ b/zaphod-v6.2.patch @@ -0,0 +1,3918 @@ +Index: 2.6.11/fs/proc/array.c +=================================================================== +--- 2.6.11.orig/fs/proc/array.c 2005-04-14 19:29:15.616973568 -0500 ++++ 2.6.11/fs/proc/array.c 2005-04-15 10:46:00.818575480 -0500 +@@ -170,7 +170,7 @@ + "Uid:\t%d\t%d\t%d\t%d\n" + "Gid:\t%d\t%d\t%d\t%d\n", + get_task_state(p), +- (p->sleep_avg/1024)*100/(1020000000/1024), ++ map_proportion_rnd(avg_sleep_rate(p), 100), + p->tgid, + p->pid, pid_alive(p) ? p->group_leader->real_parent->tgid : 0, + pid_alive(p) && p->ptrace ? p->parent->pid : 0, +Index: 2.6.11/fs/proc/base.c +=================================================================== +--- 2.6.11.orig/fs/proc/base.c 2005-04-14 19:29:15.617973940 -0500 ++++ 2.6.11/fs/proc/base.c 2005-04-15 10:46:00.728542000 -0500 +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + #include "internal.h" + + /* +@@ -95,6 +96,9 @@ + #ifdef CONFIG_SCHEDSTATS + PROC_TID_SCHEDSTAT, + #endif ++ PROC_TID_CPU_STATS, ++ PROC_TID_CPU_RATE_CAP, ++ PROC_TID_CPU_RATE_HARD_CAP, + #ifdef CONFIG_SECURITY + PROC_TID_ATTR, + PROC_TID_ATTR_CURRENT, +@@ -178,6 +182,9 @@ + #ifdef CONFIG_AUDITSYSCALL + E(PROC_TID_LOGINUID, "loginuid", S_IFREG|S_IWUSR|S_IRUGO), + #endif ++ E(PROC_TID_CPU_STATS, "cpustats", S_IFREG|S_IRUGO), ++ E(PROC_TID_CPU_RATE_CAP, "cpu_rate_cap", S_IFREG|S_IRUGO|S_IWUSR), ++ E(PROC_TID_CPU_RATE_HARD_CAP, "cpu_rate_hard_cap", S_IFREG|S_IRUGO|S_IWUSR), + {0,0,NULL,0} + }; + +@@ -808,6 +815,98 @@ + }; + #endif + ++static ssize_t cpu_rate_cap_read(struct file * file, char * buf, ++ size_t count, loff_t *ppos) ++{ ++ struct task_struct *task = PROC_I(file->f_dentry->d_inode)->task; ++ char buffer[64]; ++ size_t len; ++ unsigned long hcppt = proportion_to_ppt(task->cpu_rate_cap); ++ ++ if (*ppos) ++ return 0; ++ *ppos = len = sprintf(buffer, "%lu\n", hcppt); ++ if (copy_to_user(buf, buffer, len)) ++ return -EFAULT; ++ ++ return len; ++} ++ ++static ssize_t cpu_rate_cap_write(struct file * file, const char * buf, ++ size_t count, loff_t *ppos) ++{ ++ struct task_struct *task = PROC_I(file->f_dentry->d_inode)->task; ++ char buffer[128] = ""; ++ char *endptr = NULL; ++ unsigned long hcppt; ++ int res; ++ ++ ++ if ((count > 63) || *ppos) ++ return -EFBIG; ++ if (copy_from_user(buffer, buf, count)) ++ return -EFAULT; ++ hcppt = simple_strtoul(buffer, &endptr, 0); ++ if ((endptr == buffer) || (hcppt == ULONG_MAX)) ++ return -EINVAL; ++ ++ if ((res = set_cpu_rate_cap(task, hcppt)) != 0) ++ return res; ++ ++ return count; ++} ++ ++struct file_operations proc_cpu_rate_cap_operations = { ++ read: cpu_rate_cap_read, ++ write: cpu_rate_cap_write, ++}; ++ ++ssize_t cpu_rate_hard_cap_read(struct file * file, char * buf, ++ size_t count, loff_t *ppos) ++{ ++ struct task_struct *task = PROC_I(file->f_dentry->d_inode)->task; ++ char buffer[64]; ++ size_t len; ++ unsigned long long hcppt = proportion_to_ppt(task->cpu_rate_hard_cap); ++ ++ if (*ppos) ++ return 0; ++ *ppos = len = sprintf(buffer, "%llu\n", hcppt); ++ if (copy_to_user(buf, buffer, len)) ++ return -EFAULT; ++ ++ return len; ++} ++ ++ssize_t cpu_rate_hard_cap_write(struct file * file, const char * buf, ++ size_t count, loff_t *ppos) ++{ ++ struct task_struct *task = PROC_I(file->f_dentry->d_inode)->task; ++ char buffer[128] = ""; ++ char *endptr = NULL; ++ unsigned long long hcppt; ++ int res; ++ ++ ++ if ((count > 63) || *ppos) ++ return -EFBIG; ++ if (copy_from_user(buffer, buf, count)) ++ return -EFAULT; ++ hcppt = simple_strtoul(buffer, &endptr, 0); ++ if ((endptr == buffer) || (hcppt == ULONG_MAX)) ++ return -EINVAL; ++ ++ if ((res = set_cpu_rate_hard_cap(task, hcppt)) != 0) ++ return res; ++ ++ return count; ++} ++ ++struct file_operations proc_cpu_rate_hard_cap_operations = { ++ read: cpu_rate_hard_cap_read, ++ write: cpu_rate_hard_cap_write, ++}; ++ + static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) + { + struct inode *inode = dentry->d_inode; +@@ -1498,6 +1597,16 @@ + inode->i_fop = &proc_loginuid_operations; + break; + #endif ++ case PROC_TID_CPU_STATS: ++ inode->i_fop = &proc_info_file_operations; ++ ei->op.proc_read = task_sched_cpustats; ++ break; ++ case PROC_TID_CPU_RATE_CAP: ++ inode->i_fop = &proc_cpu_rate_cap_operations; ++ break; ++ case PROC_TID_CPU_RATE_HARD_CAP: ++ inode->i_fop = &proc_cpu_rate_hard_cap_operations; ++ break; + default: + printk("procfs: impossible type (%d)",p->type); + iput(inode); +Index: 2.6.11/fs/proc/proc_misc.c +=================================================================== +--- 2.6.11.orig/fs/proc/proc_misc.c 2005-04-14 19:29:15.617973940 -0500 ++++ 2.6.11/fs/proc/proc_misc.c 2005-04-15 10:46:00.541472436 -0500 +@@ -44,6 +44,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -566,6 +567,7 @@ + {"cmdline", cmdline_read_proc}, + {"locks", locks_read_proc}, + {"execdomains", execdomains_read_proc}, ++ {"cpustats", cpustats_read_proc}, + {NULL,} + }; + for (p = simple_ones; p->name; p++) +Index: 2.6.11/include/linux/init_task.h +=================================================================== +--- 2.6.11.orig/include/linux/init_task.h 2005-04-14 19:29:15.617973940 -0500 ++++ 2.6.11/include/linux/init_task.h 2005-04-15 10:46:00.870568836 -0500 +@@ -92,6 +92,9 @@ + .real_timer = { \ + .function = it_real_fn \ + }, \ ++ .sinbin_timer = { \ ++ .function = sinbin_release_fn \ ++ }, \ + .group_info = &init_groups, \ + .cap_effective = CAP_INIT_EFF_SET, \ + .cap_inheritable = CAP_INIT_INH_SET, \ +@@ -112,6 +115,11 @@ + .proc_lock = SPIN_LOCK_UNLOCKED, \ + .switch_lock = SPIN_LOCK_UNLOCKED, \ + .journal_info = NULL, \ ++ INIT_CPUSTATS, \ ++ .cpu_rate_cap = PROPORTION_ONE, \ ++ .cpu_rate_hard_cap = PROPORTION_ONE, \ ++ .rq = NULL, \ ++ SCHED_ZAPHOD_INIT, \ + } + + +Index: 2.6.11/include/linux/sched.h +=================================================================== +--- 2.6.11.orig/include/linux/sched.h 2005-04-14 19:29:15.618974312 -0500 ++++ 2.6.11/include/linux/sched.h 2005-04-15 10:50:05.428013764 -0500 +@@ -32,6 +32,8 @@ + #include + #include + #include ++#include ++#include + + struct exec_domain; + +@@ -203,7 +205,6 @@ + extern void arch_unmap_area(struct vm_area_struct *area); + extern void arch_unmap_area_topdown(struct vm_area_struct *area); + +- + struct mm_struct { + struct vm_area_struct * mmap; /* list of VMAs */ + struct rb_root mm_rb; +@@ -343,8 +344,9 @@ + /* + * Priority of a process goes from 0..MAX_PRIO-1, valid RT + * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL tasks are +- * in the range MAX_RT_PRIO..MAX_PRIO-1. Priority values ++ * in the range MIN_SN_PRIO..MAX_PRIO-1 (plus bonuses). Priority values + * are inverted: lower p->prio value means higher priority. ++ * MAX_RT_PRIO is reserved for well behaved PF_UNPRIV_RT tasks. + * + * The MAX_USER_RT_PRIO value allows the actual maximum + * RT priority to be separate from the value exported to +@@ -356,7 +358,13 @@ + #define MAX_USER_RT_PRIO 100 + #define MAX_RT_PRIO MAX_USER_RT_PRIO + +-#define MAX_PRIO (MAX_RT_PRIO + 40) ++#define MIN_NORMAL_PRIO (MAX_RT_PRIO + 1) ++#define MAX_PRIO (MIN_NORMAL_PRIO + 40) ++/* ++ * Making IDLE_PRIO bigger than 159 would require modification of bitmaps ++ */ ++#define IDLE_PRIO 159 ++#define BGND_PRIO (IDLE_PRIO - 1) + + #define rt_task(p) (unlikely((p)->prio < MAX_RT_PRIO)) + +@@ -387,7 +395,7 @@ + extern struct user_struct root_user; + #define INIT_USER (&root_user) + +-typedef struct prio_array prio_array_t; ++typedef struct runqueue runqueue_t; + struct backing_dev_info; + struct reclaim_state; + +@@ -521,7 +529,6 @@ + #define GROUP_AT(gi, i) \ + ((gi)->blocks[(i)/NGROUPS_PER_BLOCK][(i)%NGROUPS_PER_BLOCK]) + +- + struct audit_context; /* See audit.c */ + struct mempolicy; + +@@ -536,15 +543,20 @@ + + int prio, static_prio; + struct list_head run_list; +- prio_array_t *array; +- +- unsigned long sleep_avg; +- unsigned long long timestamp, last_ran; +- int activated; ++ runqueue_t *rq; ++ struct runq_cpustats *csrq; ++ struct sched_zaphod_runq_data *zrq; ++ ++ struct sched_zaphod zaphod; ++ struct task_cpustats cpustats; ++ unsigned long cpu_rate_cap, min_cpu_rate_cap; ++ unsigned long cpu_rate_hard_cap; ++ struct timer_list sinbin_timer; ++ unsigned long long last_ran; + + unsigned long policy; + cpumask_t cpus_allowed; +- unsigned int time_slice, first_time_slice; ++ unsigned long time_slice; + + #ifdef CONFIG_SCHEDSTATS + struct sched_info sched_info; +@@ -735,6 +747,13 @@ + #define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */ + #define PF_SYNCWRITE 0x00200000 /* I am doing a sync write */ + #define PF_BORROWED_MM 0x00400000 /* I am a kthread doing use_mm */ ++#define PF_SINBINNED 0x00800000 /* I am sinbinned */ ++#define PF_UNPRIV_RT 0x01000000 /* I wanted to be RT but had insufficient privilege*/ ++#define PF_UISLEEP 0x02000000 /* Uninterruptible sleep */ ++ ++#define task_is_sinbinned(p) (unlikely(((p)->flags & PF_SINBINNED) != 0)) ++#define task_is_unpriv_rt(p) (unlikely(((p)->flags & PF_UNPRIV_RT) != 0)) ++#define task_is_bgnd(p) (unlikely((p)->cpu_rate_cap == 0)) + + /* + * Only the _current_ task can read/write to tsk->flags, but other +@@ -761,6 +780,13 @@ + #define tsk_used_math(p) ((p)->flags & PF_USED_MATH) + #define used_math() tsk_used_math(current) + ++extern void put_task_in_sinbin(struct task_struct *p, unsigned long durn); ++extern void sinbin_release_fn(unsigned long arg); ++ ++/* set cpu rate caps in parts per thousand */ ++extern int set_cpu_rate_cap(struct task_struct *p, unsigned long new_cap); ++extern int set_cpu_rate_hard_cap(struct task_struct *p, unsigned long new_cap); ++ + #ifdef CONFIG_SMP + extern int set_cpus_allowed(task_t *p, cpumask_t new_mask); + #else +@@ -1148,10 +1174,7 @@ + return p->thread_info->cpu; + } + +-static inline void set_task_cpu(struct task_struct *p, unsigned int cpu) +-{ +- p->thread_info->cpu = cpu; +-} ++extern FASTCALL(void set_task_cpu(struct task_struct *p, unsigned int cpu)); + + #else + +Index: 2.6.11/include/linux/sched_cpustats.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ 2.6.11/include/linux/sched_cpustats.h 2005-04-15 10:46:29.045185928 -0500 +@@ -0,0 +1,160 @@ ++#ifndef _LINUX_SCHED_CPUSTATS_H ++#define _LINUX_SCHED_CPUSTATS_H ++ ++#include ++ ++/* ++ * Fixed denominator rational numbers for use by the CPU scheduler ++ */ ++#define SCHED_AVG_OFFSET 4 ++/* ++ * Get the rounded integer value of a scheduling statistic average field ++ * i.e. those fields whose names begin with avg_ ++ */ ++#define SCHED_AVG_RND(x) \ ++ (((x) + (1 << (SCHED_AVG_OFFSET - 1))) >> (SCHED_AVG_OFFSET)) ++#define SCHED_AVG_REAL(a) ((a) << SCHED_AVG_OFFSET) ++ ++#define INITIAL_CPUSTATS_TIMESTAMP \ ++ ((unsigned long long)INITIAL_JIFFIES * (1000000000ULL / HZ)) ++ ++struct runq_cpustats { ++#ifdef CONFIG_SMP ++ unsigned long long timestamp_last_tick; ++#endif ++ unsigned long long total_delay; ++ unsigned long long total_rt_delay; ++ unsigned long long total_intr_delay; ++ unsigned long long total_rt_intr_delay; ++ unsigned long long total_fork_delay; ++ unsigned long long total_sinbin; ++}; ++ ++/* ++ * Scheduling statistics for a task/thread ++ */ ++struct task_cpustats { ++ unsigned long long timestamp; ++ unsigned long long total_wake_ups; ++ unsigned long long intr_wake_ups; ++ unsigned long long total_sleep; ++ unsigned long long avg_sleep_per_cycle; ++ unsigned long long total_cpu; ++ unsigned long long avg_cpu_per_cycle; ++ unsigned long long total_delay; ++ unsigned long long avg_delay_per_cycle; ++ unsigned long long total_sinbin; ++ unsigned long long avg_cycle_length; ++ unsigned long cpu_usage_rate; ++ unsigned int flags; ++}; ++ ++#define CPUSTATS_WOKEN_FOR_INTR_FL (1 << 0) ++#define CPUSTATS_JUST_FORKED_FL (1 << 1) ++ ++#define INIT_CPUSTATS \ ++ .cpustats = { .timestamp = INITIAL_CPUSTATS_TIMESTAMP, 0, }, \ ++ .csrq = NULL ++ ++ ++struct task_struct; ++ ++extern void init_runq_cpustats(unsigned int cpu); ++extern struct runq_cpustats *cpu_runq_cpustats(unsigned int cpu); ++#ifdef CONFIG_SMP ++extern unsigned long long adjusted_sched_clock(const struct task_struct *p); ++extern void set_task_runq_cpustats(struct task_struct *p, unsigned int cpu); ++static inline void tick_runq_cpustats(struct runq_cpustats *rcsp, unsigned long long now) ++{ ++ rcsp->timestamp_last_tick = now; ++} ++#else ++#define adjusted_sched_clock(p) sched_clock() ++static inline void set_task_runq_cpustats(struct task_struct *p, unsigned int cpu) {} ++static inline void tick_runq_cpustats(struct runq_cpustats *rcsp, unsigned long long now) {} ++#endif ++ ++extern void initialize_cpustats(struct task_struct *p, unsigned long long now); ++extern void delta_sleep_cpustats(struct task_struct *p, unsigned long long now); ++extern void delta_cpu_cpustats(struct task_struct *p, unsigned long long now); ++extern void delta_delay_cpustats(struct task_struct *p, unsigned long long now); ++extern void delta_rq_delay_cpustats(struct task_struct *p, unsigned long long delta); ++extern void update_cpustats_at_wake_up(struct task_struct *p, unsigned long long now); ++extern void update_cpustats_at_end_of_ts(struct task_struct *p, unsigned long long now); ++ ++/* ++ * Get "up to date" scheduling statistics for the given task ++ * This function should be used if reliable scheduling statistitcs are required ++ * outside the scheduler itself as the relevant fields in the task structure ++ * are not "up to date" NB the possible difference between those in the task ++ * structure and the correct values could be quite large for sleeping tasks. ++ */ ++extern int get_task_cpustats(struct task_struct*, struct task_cpustats*); ++ ++/* ++ * Scheduling statistics for a CPU ++ */ ++struct cpu_cpustats { ++ unsigned long long timestamp; ++ unsigned long long total_idle; ++ unsigned long long total_busy; ++ unsigned long long total_delay; ++ unsigned long long total_rt_delay; ++ unsigned long long total_intr_delay; ++ unsigned long long total_rt_intr_delay; ++ unsigned long long total_fork_delay; ++ unsigned long long total_sinbin; ++ unsigned long long nr_switches; ++}; ++ ++/* ++ * Get scheduling statistics for the nominated CPU ++ */ ++extern int get_cpu_cpustats(unsigned int, struct cpu_cpustats*); ++ ++/* ++ * Make scheduling statistics available via /proc ++ */ ++extern int task_sched_cpustats(struct task_struct *p, char *buffer); ++extern int cpustats_read_proc(char *page, char **start, off_t off, int count, ++ int *eof, void *data); ++ ++ ++/* ++ * CPU rate statistics are estimated as a proportions (i.e. real numbers in the ++ * rang 0 to 1 inclusive) using fixed denominator rational numbers. ++ * The denominator (PROPORTION_ONE) must be less than to 2^24 ++ */ ++#define PROPORTION_OFFSET 23 ++#define PROPORTION_ONE (1ULL << PROPORTION_OFFSET) ++#define PROP_FM_PPT(a) (((unsigned long long)(a) * PROPORTION_ONE) / 1000) ++ ++/* Require: a <= b */ ++extern unsigned long calc_proportion(unsigned long long a, unsigned long long b); ++extern unsigned long map_proportion(unsigned long prop, unsigned long range); ++#define map_proportion_rnd(p, r) map_proportion((p) >> 1, ((r) << 1) + 1) ++extern unsigned long proportion_to_ppt(unsigned long proportion); ++extern unsigned long ppt_to_proportion(unsigned long ppt); ++ ++extern unsigned long avg_cpu_usage_rate(const struct task_struct*); ++extern unsigned long avg_sleep_rate(const struct task_struct*); ++extern unsigned long avg_cpu_delay_rate(const struct task_struct*); ++extern unsigned long delay_in_jiffies_for_usage(const struct task_struct*, unsigned long); ++ ++extern int do_proc_proportion(ctl_table *ctp, int write, struct file *fp, ++ void __user *buffer, size_t *lenp, loff_t *ppos); ++ ++#ifdef CONFIG_CPUSCHED_ZAPHOD ++#define TASK_CPUSTATS(p) (p)->u.zaphod.cpustats ++#define RUNQ_CPUSTATS(p) (p)->u.zaphod.csrq ++/* set/get cpu rate caps in parts per thousand */ ++extern int set_cpu_rate_cap(struct task_struct *p, unsigned long new_cap); ++extern int set_cpu_rate_hard_cap(struct task_struct *p, unsigned long new_cap); ++extern unsigned int get_cpu_rate_cap(struct task_struct *p); ++extern unsigned int get_cpu_rate_hard_cap(struct task_struct *p); ++#else ++#define TASK_CPUSTATS(p) (p)->cpustats ++#define RUNQ_CPUSTATS(p) (p)->csrq ++#endif ++ ++#endif +Index: 2.6.11/include/linux/sched_zaphod.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ 2.6.11/include/linux/sched_zaphod.h 2005-04-15 10:46:00.865566976 -0500 +@@ -0,0 +1,160 @@ ++#ifndef _LINUX_SCHED_ZAPHOD_H ++#define _LINUX_SCHED_ZAPHOD_H ++ ++#include ++#include ++ ++#ifdef CONFIG_CPUSCHED_ZAPHOD ++/* ++ * Making IDLE_PRIO bigger than 159 would require modification of bitmaps ++ */ ++#define ZAPHOD_IDLE_PRIO 159 ++#define ZAPHOD_BGND_PRIO (ZAPHOD_IDLE_PRIO - 1) ++#define ZAPHOD_MIN_NORMAL_PRIO (MAX_RT_PRIO + 1) ++#define ZAPHOD_MAX_PRIO (ZAPHOD_MIN_NORMAL_PRIO + 40) ++#else ++#define ZAPHOD_BGND_PRIO BGND_PRIO ++/* defined in sched.c */ ++extern unsigned long time_slice; ++#endif ++ ++/* ++ * For entitlemnet based scheduling a task's shares will be determined from ++ * their "nice"ness ++ */ ++#define EB_SHARES_PER_NICE 5 ++#define DEFAULT_EB_SHARES (20 * EB_SHARES_PER_NICE) ++#define MAX_EB_SHARES (DEFAULT_EB_SHARES * DEFAULT_EB_SHARES) ++ ++struct sched_zaphod_runq_data { ++ unsigned long avg_nr_running; ++ atomic_t eb_yardstick; ++ atomic_t eb_ticks_to_decay; ++}; ++ ++extern void zaphod_init_cpu_runq_data(unsigned int cpu); ++extern struct sched_zaphod_runq_data *zaphod_cpu_runq_data(unsigned int cpu); ++extern void zaphod_runq_data_tick(struct sched_zaphod_runq_data *zrq, unsigned long numr); ++ ++struct sched_zaphod { ++ unsigned int pre_bonus_priority; ++ unsigned int interactive_bonus; ++ unsigned int throughput_bonus; ++ unsigned int eb_shares; ++}; ++ ++#define ZAPHOD_TASK_DATA_INIT() \ ++ { .pre_bonus_priority = (ZAPHOD_BGND_PRIO - 20), \ ++ .eb_shares = DEFAULT_EB_SHARES, \ ++ .interactive_bonus = 0, \ ++ .throughput_bonus = 0, \ ++ } ++ ++#define SCHED_ZAPHOD_INIT \ ++ .zrq = NULL, \ ++ .zaphod = ZAPHOD_TASK_DATA_INIT() ++ ++#ifdef CONFIG_CPUSCHED_ZAPHOD ++static inline struct sched_zaphod zaphod_task_data_init(void) { ++ struct sched_zaphod ret = ZAPHOD_TASK_DATA_INIT(); ++ ++ return ret; ++} ++#endif ++ ++struct task_struct; ++ ++extern void zaphod_fork(struct task_struct *p); ++extern unsigned int zaphod_effective_prio(struct task_struct *p); ++extern void zaphod_reassess_at_activation(struct task_struct *p); ++extern void zaphod_reassess_at_end_of_ts(struct task_struct *p); ++extern void zaphod_reassess_at_sinbin_release(struct task_struct *p); ++extern void zaphod_reassess_at_renice(struct task_struct *p); ++extern void zaphod_reassess_at_new_cap(struct task_struct *p); ++ ++#ifdef CONFIG_SYSCTL ++#ifndef CONFIG_CPUSCHED_ZAPHOD ++extern struct ctl_table zaphod_ctl_table[]; ++#else ++extern unsigned int max_ia_bonus; ++extern unsigned int max_max_ia_bonus; ++extern unsigned int initial_ia_bonus; ++extern unsigned int max_tpt_bonus; ++extern unsigned int max_max_tpt_bonus; ++extern unsigned long ia_threshold; ++extern unsigned long cpu_hog_threshold; ++#define ZAPHOD_MODE_BUFFER_LEN 16 ++extern char current_zaphod_mode[ZAPHOD_MODE_BUFFER_LEN]; ++int proc_zaphod_mode(ctl_table *ctp, int write, struct file *fp, ++ void __user *buffer, size_t *lenp, loff_t *ppos); ++#endif ++ ++#define ZAPHOD_SYSCTL_FNS() \ ++ CPU_SCHED_ZAPHOD_MAX_IA_BONUS, \ ++ CPU_SCHED_ZAPHOD_INITIAL_IA_BONUS, \ ++ CPU_SCHED_ZAPHOD_IA_THRESHOLD, \ ++ CPU_SCHED_ZAPHOD_CPU_HOG_THRESHOLD, \ ++ CPU_SCHED_ZAPHOD_MAX_TPT_BONUS, \ ++ CPU_SCHED_ZAPHOD_MODE ++ ++#define ZAPHOD_CTL_TABLE_INIT() \ ++{ \ ++ .ctl_name = CPU_SCHED_ZAPHOD_MAX_IA_BONUS, \ ++ .procname = "max_ia_bonus", \ ++ .data = &max_ia_bonus, \ ++ .maxlen = sizeof (unsigned int), \ ++ .mode = 0644, \ ++ .proc_handler = &proc_dointvec_minmax, \ ++ .extra1 = NULL, \ ++ .extra2 = (void *)&max_max_ia_bonus \ ++}, \ ++{ \ ++ .ctl_name = CPU_SCHED_ZAPHOD_INITIAL_IA_BONUS, \ ++ .procname = "initial_ia_bonus", \ ++ .data = &initial_ia_bonus, \ ++ .maxlen = sizeof (unsigned int), \ ++ .mode = 0644, \ ++ .proc_handler = &proc_dointvec_minmax, \ ++ .extra1 = (void *)&zero, \ ++ .extra2 = (void *)&max_max_ia_bonus \ ++}, \ ++{ \ ++ .ctl_name = CPU_SCHED_ZAPHOD_IA_THRESHOLD, \ ++ .procname = "ia_threshold", \ ++ .data = &ia_threshold, \ ++ .maxlen = sizeof (unsigned long), \ ++ .mode = 0644, \ ++ .proc_handler = &do_proc_proportion, \ ++ .extra1 = NULL, \ ++ .extra2 = NULL \ ++}, \ ++{ \ ++ .ctl_name = CPU_SCHED_ZAPHOD_CPU_HOG_THRESHOLD, \ ++ .procname = "cpu_hog_threshold", \ ++ .data = &cpu_hog_threshold, \ ++ .maxlen = sizeof (unsigned long), \ ++ .mode = 0644, \ ++ .proc_handler = &do_proc_proportion, \ ++ .extra1 = NULL, \ ++ .extra2 = NULL \ ++}, \ ++{ \ ++ .ctl_name = CPU_SCHED_ZAPHOD_MAX_TPT_BONUS, \ ++ .procname = "max_tpt_bonus", \ ++ .data = &max_tpt_bonus, \ ++ .maxlen = sizeof (unsigned int), \ ++ .mode = 0644, \ ++ .proc_handler = &proc_dointvec_minmax, \ ++ .extra1 = (void *)&zero, \ ++ .extra2 = (void *)&max_max_tpt_bonus \ ++}, \ ++{ \ ++ .ctl_name = CPU_SCHED_ZAPHOD_MODE, \ ++ .procname = "mode", \ ++ .data = ¤t_zaphod_mode, \ ++ .maxlen = ZAPHOD_MODE_BUFFER_LEN, \ ++ .mode = 0644, \ ++ .proc_handler = &proc_zaphod_mode, \ ++} ++#endif ++#endif +Index: 2.6.11/include/linux/sysctl.h +=================================================================== +--- 2.6.11.orig/include/linux/sysctl.h 2005-04-14 19:29:15.618974312 -0500 ++++ 2.6.11/include/linux/sysctl.h 2005-04-15 10:46:00.542472808 -0500 +@@ -61,7 +61,8 @@ + CTL_DEV=7, /* Devices */ + CTL_BUS=8, /* Busses */ + CTL_ABI=9, /* Binary emulation */ +- CTL_CPU=10 /* CPU stuff (speed scaling, etc) */ ++ CTL_CPU=10, /* CPU stuff (speed scaling, etc) */ ++ CTL_CPU_SCHED=11, /* CPU scheduler stuff */ + }; + + /* CTL_BUS names: */ +@@ -803,6 +804,10 @@ + void __user *, size_t *, loff_t *); + extern int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int, + struct file *, void __user *, size_t *, loff_t *); ++typedef int (*sysctl_ul_convf_t)(unsigned long *val, void *data, int write); ++extern int do_proc_doulongvec_convf_minmax(ctl_table *, int, ++ struct file *, void __user *, size_t *, ++ loff_t *s, sysctl_ul_convf_t, void __user*); + + extern int do_sysctl (int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, +Index: 2.6.11/kernel/Makefile +=================================================================== +--- 2.6.11.orig/kernel/Makefile 2005-04-14 19:29:15.618974312 -0500 ++++ 2.6.11/kernel/Makefile 2005-04-15 10:46:00.870568836 -0500 +@@ -7,7 +7,7 @@ + sysctl.o capability.o ptrace.o timer.o user.o \ + signal.o sys.o kmod.o workqueue.o pid.o \ + rcupdate.o intermodule.o extable.o params.o posix-timers.o \ +- kthread.o wait.o kfifo.o sys_ni.o ++ kthread.o wait.o kfifo.o sys_ni.o sched_cpustats.o sched_zaphod.o + + obj-$(CONFIG_FUTEX) += futex.o + obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o +Index: 2.6.11/kernel/sched.c +=================================================================== +--- 2.6.11.orig/kernel/sched.c 2005-04-14 19:29:15.619974684 -0500 ++++ 2.6.11/kernel/sched.c 2005-04-15 10:46:29.048187044 -0500 +@@ -51,125 +51,57 @@ + + /* + * Convert user-nice values [ -20 ... 0 ... 19 ] +- * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ], ++ * to static priority [ MIN_NORMAL_PRIO..MAX_PRIO-1 ], + * and back. + */ +-#define NICE_TO_PRIO(nice) (MAX_RT_PRIO + (nice) + 20) +-#define PRIO_TO_NICE(prio) ((prio) - MAX_RT_PRIO - 20) ++#define NICE_TO_PRIO(nice) (MIN_NORMAL_PRIO + (nice) + 20) ++#define PRIO_TO_NICE(prio) ((prio) - MIN_NORMAL_PRIO - 20) + #define TASK_NICE(p) PRIO_TO_NICE((p)->static_prio) + + /* +- * 'User priority' is the nice value converted to something we +- * can work with better when scaling various scheduler parameters, +- * it's a [ 0 ... 39 ] range. +- */ +-#define USER_PRIO(p) ((p)-MAX_RT_PRIO) +-#define TASK_USER_PRIO(p) USER_PRIO((p)->static_prio) +-#define MAX_USER_PRIO (USER_PRIO(MAX_PRIO)) +- +-/* +- * Some helpers for converting nanosecond timing to jiffy resolution +- */ +-#define NS_TO_JIFFIES(TIME) ((TIME) / (1000000000 / HZ)) +-#define JIFFIES_TO_NS(TIME) ((TIME) * (1000000000 / HZ)) +- +-/* + * These are the 'tuning knobs' of the scheduler: + * +- * Minimum timeslice is 5 msecs (or 1 jiffy, whichever is larger), +- * default timeslice is 100 msecs, maximum timeslice is 800 msecs. +- * Timeslices get refilled after they expire. ++ * Default configurable timeslice is 100 msecs, maximum configurable ++ * timeslice is 1000 msecs and minumum configurable timeslice is 1 jiffy. ++ * Timeslices get renewed on task creation, on wake up and after they expire. + */ +-#define MIN_TIMESLICE max(5 * HZ / 1000, 1) ++#define MIN_TIMESLICE 1 + #define DEF_TIMESLICE (100 * HZ / 1000) +-#define ON_RUNQUEUE_WEIGHT 30 +-#define CHILD_PENALTY 95 +-#define PARENT_PENALTY 100 +-#define EXIT_WEIGHT 3 +-#define PRIO_BONUS_RATIO 25 +-#define MAX_BONUS (MAX_USER_PRIO * PRIO_BONUS_RATIO / 100) +-#define INTERACTIVE_DELTA 2 +-#define MAX_SLEEP_AVG (DEF_TIMESLICE * MAX_BONUS) +-#define STARVATION_LIMIT (MAX_SLEEP_AVG) +-#define NS_MAX_SLEEP_AVG (JIFFIES_TO_NS(MAX_SLEEP_AVG)) +- +-/* +- * If a task is 'interactive' then we reinsert it in the active +- * array after it has expired its current timeslice. (it will not +- * continue to run immediately, it will still roundrobin with +- * other interactive tasks.) +- * +- * This part scales the interactivity limit depending on niceness. +- * +- * We scale it linearly, offset by the INTERACTIVE_DELTA delta. +- * Here are a few examples of different nice levels: +- * +- * TASK_INTERACTIVE(-20): [1,1,1,1,1,1,1,1,1,0,0] +- * TASK_INTERACTIVE(-10): [1,1,1,1,1,1,1,0,0,0,0] +- * TASK_INTERACTIVE( 0): [1,1,1,1,0,0,0,0,0,0,0] +- * TASK_INTERACTIVE( 10): [1,1,0,0,0,0,0,0,0,0,0] +- * TASK_INTERACTIVE( 19): [0,0,0,0,0,0,0,0,0,0,0] +- * +- * (the X axis represents the possible -5 ... 0 ... +5 dynamic +- * priority range a task can explore, a value of '1' means the +- * task is rated interactive.) +- * +- * Ie. nice +19 tasks can never get 'interactive' enough to be +- * reinserted into the active array. And only heavily CPU-hog nice -20 +- * tasks will be expired. Default nice 0 tasks are somewhere between, +- * it takes some effort for them to get interactive, but it's not +- * too hard. +- */ +- +-#define CURRENT_BONUS(p) \ +- (NS_TO_JIFFIES((p)->sleep_avg) * MAX_BONUS / \ +- MAX_SLEEP_AVG) +- +-#define GRANULARITY (10 * HZ / 1000 ? : 1) +- +-#ifdef CONFIG_SMP +-#define TIMESLICE_GRANULARITY(p) (GRANULARITY * \ +- (1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)) * \ +- num_online_cpus()) +-#else +-#define TIMESLICE_GRANULARITY(p) (GRANULARITY * \ +- (1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1))) +-#endif +- +-#define SCALE(v1,v1_max,v2_max) \ +- (v1) * (v2_max) / (v1_max) +- +-#define DELTA(p) \ +- (SCALE(TASK_NICE(p), 40, MAX_BONUS) + INTERACTIVE_DELTA) +- +-#define TASK_INTERACTIVE(p) \ +- ((p)->prio <= (p)->static_prio - DELTA(p)) ++#define MAX_TIMESLICE (1000 * HZ / 1000) + +-#define INTERACTIVE_SLEEP(p) \ +- (JIFFIES_TO_NS(MAX_SLEEP_AVG * \ +- (MAX_BONUS / 2 + DELTA((p)) + 1) / MAX_BONUS - 1)) ++/* ++ * UNPRIV_RT tasks that have a CPU usage rate less than this threshold ++ * (in parts per thousand) are treated as psuedo RT tasks ++ */ ++#define DEFAULT_UNPRIV_RT_THRESHOLD 10 ++unsigned long unpriv_rt_threshold = PROP_FM_PPT(DEFAULT_UNPRIV_RT_THRESHOLD); + +-#define TASK_PREEMPTS_CURR(p, rq) \ +- ((p)->prio < (rq)->curr->prio) ++unsigned long time_slice = DEF_TIMESLICE; ++static unsigned long sched_rr_time_slice = (100 * HZ / 1000); + + /* +- * task_timeslice() scales user-nice values [ -20 ... 0 ... 19 ] +- * to time slice values: [800ms ... 100ms ... 5ms] +- * +- * The higher a thread's priority, the bigger timeslices +- * it gets during one round of execution. But even the lowest +- * priority thread gets MIN_TIMESLICE worth of execution time. ++ * Background tasks may have longer time slices as compensation + */ ++unsigned int bgnd_time_slice_multiplier = 1; ++unsigned int max_bgnd_time_slice_multiplier = 100; + +-#define SCALE_PRIO(x, prio) \ +- max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO/2), MIN_TIMESLICE) +- +-static unsigned int task_timeslice(task_t *p) ++static unsigned long task_timeslice(const task_t *p) + { +- if (p->static_prio < NICE_TO_PRIO(0)) +- return SCALE_PRIO(DEF_TIMESLICE*4, p->static_prio); +- else +- return SCALE_PRIO(DEF_TIMESLICE, p->static_prio); ++ if (rt_task(p)) ++ return sched_rr_time_slice; ++ ++ /* hard capped tasks that never use their full time slice evade ++ * the sinbin so we need to reduce the size of their time slice ++ * to reduce the size of the hole that they slip through. ++ * It would be unwise to close it completely. ++ */ ++ if (unlikely(p->cpustats.cpu_usage_rate > p->cpu_rate_hard_cap)) ++ return 1; ++ ++ if (unlikely(p->prio == BGND_PRIO)) ++ return time_slice * bgnd_time_slice_multiplier; ++ ++ return time_slice; + } + #define task_hot(p, now, sd) ((long long) ((now) - (p)->last_ran) \ + < (long long) (sd)->cache_hot_time) +@@ -177,15 +109,11 @@ + /* + * These are the runqueue data structures: + */ ++#define NUM_PRIO_SLOTS (IDLE_PRIO + 1) + +-#define BITMAP_SIZE ((((MAX_PRIO+1+7)/8)+sizeof(long)-1)/sizeof(long)) +- +-typedef struct runqueue runqueue_t; +- +-struct prio_array { +- unsigned int nr_active; +- unsigned long bitmap[BITMAP_SIZE]; +- struct list_head queue[MAX_PRIO]; ++struct prio_slot { ++ unsigned int prio; ++ struct list_head queue; + }; + + /* +@@ -215,13 +143,13 @@ + * it on another CPU. Always updated under the runqueue lock: + */ + unsigned long nr_uninterruptible; +- +- unsigned long expired_timestamp; + unsigned long long timestamp_last_tick; + task_t *curr, *idle; + struct mm_struct *prev_mm; +- prio_array_t *active, *expired, arrays[2]; +- int best_expired_prio; ++ DECLARE_BITMAP(bitmap, NUM_PRIO_SLOTS); ++ struct prio_slot queues[NUM_PRIO_SLOTS - 1]; ++ unsigned long next_prom_due; ++ unsigned long pcount; + atomic_t nr_iowait; + + #ifdef CONFIG_SMP +@@ -285,16 +213,30 @@ + + #define cpu_rq(cpu) (&per_cpu(runqueues, (cpu))) + #define this_rq() (&__get_cpu_var(runqueues)) +-#define task_rq(p) cpu_rq(task_cpu(p)) ++#define task_rq(p) ((p)->rq) + #define cpu_curr(cpu) (cpu_rq(cpu)->curr) + ++#ifdef CONFIG_SMP ++void fastcall set_task_cpu(struct task_struct *p, unsigned int cpu) ++{ ++ BUG_ON(!list_empty(&p->run_list)); ++ ++ p->thread_info->cpu = cpu; ++ p->rq = cpu_rq(cpu); ++ set_task_runq_cpustats(p, cpu); ++ p->zrq = zaphod_cpu_runq_data(cpu); ++} ++#endif ++ + /* + * Default context-switch locking: + */ + #ifndef prepare_arch_switch + # define prepare_arch_switch(rq, next) do { } while (0) + # define finish_arch_switch(rq, next) spin_unlock_irq(&(rq)->lock) +-# define task_running(rq, p) ((rq)->curr == (p)) ++# define task_is_running(p) (task_rq(p)->curr == (p)) ++#else ++# define task_is_running(p) task_running(task_rq(p), p) + #endif + + /* +@@ -560,150 +502,157 @@ + #define sched_info_switch(t, next) do { } while (0) + #endif /* CONFIG_SCHEDSTATS */ + ++static inline int task_queued(const task_t *task) ++{ ++ return !list_empty(&task->run_list); ++} ++ + /* + * Adding/removing a task to/from a priority array: + */ +-static void dequeue_task(struct task_struct *p, prio_array_t *array) ++static void dequeue_task(struct task_struct *p) + { +- array->nr_active--; +- list_del(&p->run_list); +- if (list_empty(array->queue + p->prio)) +- __clear_bit(p->prio, array->bitmap); ++ /* ++ * Initialize after removal from the list so that list_empty() works ++ * as a means for testing whether the task is runnable ++ * If p is the last task in this priority slot then slotp will be ++ * a pointer to the head of the list in the sunqueue structure ++ * NB we can't use p->prio for bitmap as task may have been ++ * promoted ++ */ ++ struct list_head *slotp = p->run_list.next; ++ ++ list_del_init(&p->run_list); ++ if (list_empty(slotp)) { ++ /* Take the opportunity to update p->prio */ ++ p->prio = list_entry(slotp, struct prio_slot, queue)->prio; ++ __clear_bit(p->prio, p->rq->bitmap); ++ } + } + +-static void enqueue_task(struct task_struct *p, prio_array_t *array) ++static void enqueue_task(struct task_struct *p) + { ++ runqueue_t *rq = task_rq(p); ++ + sched_info_queued(p); +- list_add_tail(&p->run_list, array->queue + p->prio); +- __set_bit(p->prio, array->bitmap); +- array->nr_active++; +- p->array = array; ++ list_add_tail(&p->run_list, &rq->queues[p->prio].queue); ++ __set_bit(p->prio, rq->bitmap); + } + +-/* +- * Put task to the end of the run list without the overhead of dequeue +- * followed by enqueue. +- */ +-static void requeue_task(struct task_struct *p, prio_array_t *array) ++static inline void enqueue_task_head(struct task_struct *p) + { +- list_move_tail(&p->run_list, array->queue + p->prio); +-} ++ runqueue_t *rq = task_rq(p); + +-static inline void enqueue_task_head(struct task_struct *p, prio_array_t *array) +-{ +- list_add(&p->run_list, array->queue + p->prio); +- __set_bit(p->prio, array->bitmap); +- array->nr_active++; +- p->array = array; ++ list_add(&p->run_list, &rq->queues[p->prio].queue); ++ __set_bit(p->prio, rq->bitmap); + } + + /* + * effective_prio - return the priority that is based on the static + * priority but is modified by bonuses/penalties. +- * +- * We scale the actual sleep average [0 .... MAX_SLEEP_AVG] +- * into the -5 ... 0 ... +5 bonus/penalty range. +- * +- * We use 25% of the full 0...39 priority range so that: +- * +- * 1) nice +19 interactive tasks do not preempt nice 0 CPU hogs. +- * 2) nice -20 CPU hogs do not get preempted by nice 0 tasks. +- * +- * Both properties are important to certain workloads. + */ + static int effective_prio(task_t *p) + { +- int bonus, prio; +- + if (rt_task(p)) + return p->prio; + +- bonus = CURRENT_BONUS(p) - MAX_BONUS / 2; ++ if (task_is_unpriv_rt(p) && avg_cpu_usage_rate(p) < unpriv_rt_threshold) ++ return MAX_RT_PRIO; ++ ++ if (task_is_bgnd(p) && !(p->flags & PF_UISLEEP)) ++ return BGND_PRIO; + +- prio = p->static_prio - bonus; +- if (prio < MAX_RT_PRIO) +- prio = MAX_RT_PRIO; +- if (prio > MAX_PRIO-1) +- prio = MAX_PRIO-1; +- return prio; ++ /* using the minimum of the hard and soft caps makes things smoother */ ++ if (unlikely(avg_cpu_usage_rate(p) > p->min_cpu_rate_cap)) ++ return BGND_PRIO - 1; ++ ++ return zaphod_effective_prio(p); + } + + /* +- * __activate_task - move a task to the runqueue. ++ * Control value for promotion mechanism NB this controls severity of "nice" + */ +-static inline void __activate_task(task_t *p, runqueue_t *rq) ++unsigned long base_prom_interval = ((DEF_TIMESLICE * 15) / 10); ++ ++static inline void restart_promotions(struct runqueue *rq) ++{ ++ rq->next_prom_due = jiffies + base_prom_interval; ++ rq->pcount = 1; ++} ++ ++/* make it (relatively) easy to switch to using a timer */ ++static inline void stop_promotions(struct runqueue *rq) + { +- enqueue_task(p, rq->active); +- rq->nr_running++; + } + + /* +- * __activate_idle_task - move idle task to the _front_ of runqueue. ++ * Are promotions due? + */ +-static inline void __activate_idle_task(task_t *p, runqueue_t *rq) ++static inline int promotions_due(const runqueue_t *rq) + { +- enqueue_task_head(p, rq->active); +- rq->nr_running++; ++ return unlikely(time_after_eq(jiffies, rq->next_prom_due)) && (rq->nr_running > 1); + } + +-static void recalc_task_prio(task_t *p, unsigned long long now) ++/* ++ * Assume runqueue lock is NOT already held. ++ */ ++static void do_promotions(runqueue_t *rq) + { +- unsigned long long __sleep_time = now - p->timestamp; +- unsigned long sleep_time; ++ int idx = MIN_NORMAL_PRIO; + +- if (__sleep_time > NS_MAX_SLEEP_AVG) +- sleep_time = NS_MAX_SLEEP_AVG; +- else +- sleep_time = (unsigned long)__sleep_time; ++ spin_lock(&rq->lock); ++ rq->pcount++; ++ if (rq->nr_running < rq->pcount) { ++ rq->next_prom_due = jiffies + base_prom_interval; ++ goto out_unlock; ++ } ++ for (;;) { ++ int new_prio; ++ idx = find_next_bit(rq->bitmap, BGND_PRIO, idx + 1); ++ if (idx > (BGND_PRIO - 1)) ++ break; + +- if (likely(sleep_time > 0)) { +- /* +- * User tasks that sleep a long time are categorised as +- * idle and will get just interactive status to stay active & +- * prevent them suddenly becoming cpu hogs and starving +- * other processes. +- */ +- if (p->mm && p->activated != -1 && +- sleep_time > INTERACTIVE_SLEEP(p)) { +- p->sleep_avg = JIFFIES_TO_NS(MAX_SLEEP_AVG - +- DEF_TIMESLICE); +- } else { +- /* +- * The lower the sleep avg a task has the more +- * rapidly it will rise with sleep time. +- */ +- sleep_time *= (MAX_BONUS - CURRENT_BONUS(p)) ? : 1; ++ new_prio = idx - 1; ++ __list_splice(&rq->queues[idx].queue, rq->queues[new_prio].queue.prev); ++ INIT_LIST_HEAD(&rq->queues[idx].queue); ++ __clear_bit(idx, rq->bitmap); ++ __set_bit(new_prio, rq->bitmap); ++ } ++ /* The only prio field that needs update is the current task's */ ++ if (likely(rq->curr->prio > MIN_NORMAL_PRIO && rq->curr->prio < BGND_PRIO)) ++ rq->curr->prio--; ++ restart_promotions(rq); ++out_unlock: ++ spin_unlock(&rq->lock); ++} + +- /* +- * Tasks waking from uninterruptible sleep are +- * limited in their sleep_avg rise as they +- * are likely to be waiting on I/O +- */ +- if (p->activated == -1 && p->mm) { +- if (p->sleep_avg >= INTERACTIVE_SLEEP(p)) +- sleep_time = 0; +- else if (p->sleep_avg + sleep_time >= +- INTERACTIVE_SLEEP(p)) { +- p->sleep_avg = INTERACTIVE_SLEEP(p); +- sleep_time = 0; +- } +- } ++/* ++ * __activate_task - move a task to the runqueue. ++ */ ++static inline void __activate_task(task_t *p) ++{ ++ runqueue_t *rq = task_rq(p); + +- /* +- * This code gives a bonus to interactive tasks. +- * +- * The boost works by updating the 'average sleep time' +- * value here, based on ->timestamp. The more time a +- * task spends sleeping, the higher the average gets - +- * and the higher the priority boost gets as well. +- */ +- p->sleep_avg += sleep_time; ++ enqueue_task(p); ++ rq->nr_running++; ++ if (rq->nr_running == 2) ++ restart_promotions(rq); ++} + +- if (p->sleep_avg > NS_MAX_SLEEP_AVG) +- p->sleep_avg = NS_MAX_SLEEP_AVG; +- } +- } ++/* ++ * __activate_idle_task - move idle task to the _front_ of runqueue. ++ */ ++static inline void __activate_idle_task(runqueue_t *rq) ++{ ++ enqueue_task_head(rq->idle); ++ rq->nr_running++; ++ if (rq->nr_running == 2) ++ restart_promotions(rq); ++} + ++static void recalc_task_prio(task_t *p, unsigned long long now) ++{ ++ zaphod_reassess_at_activation(p); + p->prio = effective_prio(p); + } + +@@ -713,57 +662,80 @@ + * Update all the scheduling statistics stuff. (sleep average + * calculation, priority modifiers, etc.) + */ +-static void activate_task(task_t *p, runqueue_t *rq, int local) ++static void activate_task(task_t *p) + { +- unsigned long long now; ++ unsigned long long now = adjusted_sched_clock(p); + +- now = sched_clock(); +-#ifdef CONFIG_SMP +- if (!local) { +- /* Compensate for drifting sched_clock */ +- runqueue_t *this_rq = this_rq(); +- now = (now - this_rq->timestamp_last_tick) +- + rq->timestamp_last_tick; +- } +-#endif ++ if (!rt_task(p)) ++ recalc_task_prio(p, now); ++ ++ p->time_slice = task_timeslice(p); ++ p->flags &= ~PF_UISLEEP; ++ __activate_task(p); ++} ++ ++/* ++ * deactivate_task - remove a task from the runqueue. ++ */ ++static void deactivate_task(struct task_struct *p) ++{ ++ runqueue_t *rq = task_rq(p); + +- recalc_task_prio(p, now); ++ rq->nr_running--; ++ if (p->state == TASK_UNINTERRUPTIBLE) ++ p->flags |= PF_UISLEEP; ++ dequeue_task(p); ++ if (rq->nr_running == 1) ++ stop_promotions(rq); ++} ++ ++/* ++ * Take an active task off the runqueue for a short while ++ * Assun=mes that task's runqueue is already locked ++ */ ++void put_task_in_sinbin(struct task_struct *p, unsigned long durn) ++{ ++ if (durn == 0) ++ return; ++ deactivate_task(p); ++ p->flags |= PF_SINBINNED; ++ p->sinbin_timer.expires = jiffies + durn; ++ add_timer(&p->sinbin_timer); ++} ++ ++/* ++ * Release a task from the sinbin ++ */ ++void sinbin_release_fn(unsigned long arg) ++{ ++ unsigned long flags; ++ struct task_struct *p = (struct task_struct*)arg; ++ runqueue_t *rq = task_rq_lock(p, &flags); + + /* +- * This checks to make sure it's not an uninterruptible task +- * that is now waking up. ++ * Sinbin time is included in delay time + */ +- if (!p->activated) { +- /* +- * Tasks which were woken up by interrupts (ie. hw events) +- * are most likely of interactive nature. So we give them +- * the credit of extending their sleep time to the period +- * of time they spend on the runqueue, waiting for execution +- * on a CPU, first time around: +- */ +- if (in_interrupt()) +- p->activated = 2; +- else { +- /* +- * Normal first-time wakeups get a credit too for +- * on-runqueue time, but it will be weighted down: +- */ +- p->activated = 1; +- } ++ delta_delay_cpustats(p, adjusted_sched_clock(p)); ++ p->flags &= ~PF_SINBINNED; ++ if (!rt_task(p)) { ++ zaphod_reassess_at_sinbin_release(p); ++ p->prio = effective_prio(p); + } +- p->timestamp = now; ++ __activate_task(p); + +- __activate_task(p, rq); ++ task_rq_unlock(rq, &flags); + } + +-/* +- * deactivate_task - remove a task from the runqueue. +- */ +-static void deactivate_task(struct task_struct *p, runqueue_t *rq) ++static inline int task_needs_sinbinning(const struct task_struct *p) + { +- rq->nr_running--; +- dequeue_task(p, p->array); +- p->array = NULL; ++ return unlikely(avg_cpu_usage_rate(p) > p->cpu_rate_hard_cap) && ++ (p->state == TASK_RUNNING) && !rt_task(p) && ++ ((p->flags & PF_EXITING) == 0); ++} ++ ++static inline unsigned long required_sinbin_durn(const struct task_struct *p) ++{ ++ return delay_in_jiffies_for_usage(p, p->cpu_rate_hard_cap); + } + + /* +@@ -795,6 +767,20 @@ + } + #endif + ++/* ++ * preempt_curr_if_warranted - preempt the current task on this tasks CPU ++ * if the circumanstances warrant ++ */ ++static inline void preempt_curr_if_warranted(task_t *p) ++{ ++ /* ++ * Note that idle threads have a prio of IDLE_PRIO, for this test ++ * to be always true when they are the current task. ++ */ ++ if (p->prio < p->rq->curr->prio) ++ resched_task(p->rq->curr); ++} ++ + /** + * task_curr - is this task currently executing on a CPU? + * @p: the task in question. +@@ -830,13 +816,12 @@ + */ + static int migrate_task(task_t *p, int dest_cpu, migration_req_t *req) + { +- runqueue_t *rq = task_rq(p); +- + /* + * If the task is not on a runqueue (and not running), then + * it is sufficient to simply update the task's cpu field. + */ +- if (!p->array && !task_running(rq, p)) { ++ if (!task_queued(p) && !task_is_running(p)) { ++ delta_sleep_cpustats(p, adjusted_sched_clock(p)); + set_task_cpu(p, dest_cpu); + return 0; + } +@@ -845,7 +830,7 @@ + req->type = REQ_MOVE_TASK; + req->task = p; + req->dest_cpu = dest_cpu; +- list_add(&req->list, &rq->migration_queue); ++ list_add(&req->list, &task_rq(p)->migration_queue); + return 1; + } + +@@ -867,9 +852,9 @@ + repeat: + rq = task_rq_lock(p, &flags); + /* Must be off runqueue entirely, not preempted. */ +- if (unlikely(p->array || task_running(rq, p))) { ++ if (unlikely(task_queued(p) || task_is_running(p))) { + /* If it's preempted, we yield. It could be a while. */ +- preempted = !task_running(rq, p); ++ preempted = !task_is_running(p); + task_rq_unlock(rq, &flags); + cpu_relax(); + if (preempted) +@@ -1000,14 +985,19 @@ + if (!(old_state & state)) + goto out; + +- if (p->array) ++ if (task_queued(p)) + goto out_running; + ++ /* ++ * This is the end of one scheduling cycle and the start of the next ++ */ ++ update_cpustats_at_wake_up(p, adjusted_sched_clock(p)); ++ + cpu = task_cpu(p); + this_cpu = smp_processor_id(); + + #ifdef CONFIG_SMP +- if (unlikely(task_running(rq, p))) ++ if (unlikely(task_is_running(p))) + goto out_activate; + + new_cpu = cpu; +@@ -1079,7 +1069,7 @@ + old_state = p->state; + if (!(old_state & state)) + goto out; +- if (p->array) ++ if (task_queued(p)) + goto out_running; + + this_cpu = smp_processor_id(); +@@ -1088,14 +1078,8 @@ + + out_activate: + #endif /* CONFIG_SMP */ +- if (old_state == TASK_UNINTERRUPTIBLE) { ++ if (old_state == TASK_UNINTERRUPTIBLE) + rq->nr_uninterruptible--; +- /* +- * Tasks on involuntary sleep don't earn +- * sleep_avg beyond just interactive state. +- */ +- p->activated = -1; +- } + + /* + * Sync wakeups (i.e. those types of wakeups where the waker +@@ -1105,11 +1089,9 @@ + * the waker guarantees that the freshly woken up task is going + * to be considered on this CPU.) + */ +- activate_task(p, rq, cpu == this_cpu); +- if (!sync || cpu != this_cpu) { +- if (TASK_PREEMPTS_CURR(p, rq)) +- resched_task(rq->curr); +- } ++ activate_task(p); ++ if (!sync || cpu != this_cpu) ++ preempt_curr_if_warranted(p); + success = 1; + + out_running: +@@ -1144,6 +1126,8 @@ + */ + void fastcall sched_fork(task_t *p) + { ++ unsigned long long now; ++ + /* + * We mark the process as running here, but have not actually + * inserted it onto the runqueue yet. This guarantees that +@@ -1152,8 +1136,9 @@ + */ + p->state = TASK_RUNNING; + INIT_LIST_HEAD(&p->run_list); +- p->array = NULL; + spin_lock_init(&p->switch_lock); ++ init_timer(&p->sinbin_timer); ++ p->sinbin_timer.data = (unsigned long) p; + #ifdef CONFIG_SCHEDSTATS + memset(&p->sched_info, 0, sizeof(p->sched_info)); + #endif +@@ -1166,33 +1151,18 @@ + */ + p->thread_info->preempt_count = 1; + #endif ++ local_irq_disable(); + /* +- * Share the timeslice between parent and child, thus the +- * total amount of pending timeslices in the system doesn't change, +- * resulting in more scheduling fairness. ++ * Give the task a new timeslice. + */ +- local_irq_disable(); +- p->time_slice = (current->time_slice + 1) >> 1; ++ p->time_slice = task_timeslice(p); ++ now = sched_clock(); ++ local_irq_enable(); + /* +- * The remainder of the first timeslice might be recovered by +- * the parent if the child exits early enough. ++ * Initialize the scheduling statistics + */ +- p->first_time_slice = 1; +- current->time_slice >>= 1; +- p->timestamp = sched_clock(); +- if (unlikely(!current->time_slice)) { +- /* +- * This case is rare, it happens when the parent has only +- * a single jiffy left from its timeslice. Taking the +- * runqueue lock is not a problem. +- */ +- current->time_slice = 1; +- preempt_disable(); +- scheduler_tick(); +- local_irq_enable(); +- preempt_enable(); +- } else +- local_irq_enable(); ++ initialize_cpustats(p, now); ++ zaphod_fork(p); + } + + /* +@@ -1202,112 +1172,70 @@ + * that must be done for every newly created context, then puts the task + * on the runqueue and wakes it. + */ ++#ifdef CONFIG_SMP ++#define assigned_to_this_rq(p) (likely((p)->rq == this_rq())) ++#else ++#define assigned_to_this_rq(p) 1 ++#endif + void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags) + { + unsigned long flags; +- int this_cpu, cpu; +- runqueue_t *rq, *this_rq; ++ runqueue_t *rq; + + rq = task_rq_lock(p, &flags); +- cpu = task_cpu(p); +- this_cpu = smp_processor_id(); + + BUG_ON(p->state != TASK_RUNNING); + + schedstat_inc(rq, wunt_cnt); +- /* +- * We decrease the sleep average of forking parents +- * and children as well, to keep max-interactive tasks +- * from forking tasks that are max-interactive. The parent +- * (current) is done further down, under its lock. +- */ +- p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) * +- CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS); +- +- p->prio = effective_prio(p); + +- if (likely(cpu == this_cpu)) { ++ if (assigned_to_this_rq(p)) { + if (!(clone_flags & CLONE_VM)) { + /* + * The VM isn't cloned, so we're in a good position to + * do child-runs-first in anticipation of an exec. This + * usually avoids a lot of COW overhead. + */ +- if (unlikely(!current->array)) +- __activate_task(p, rq); +- else { ++ if (unlikely(!task_queued(current))) { ++ p->prio = effective_prio(p); ++ __activate_task(p); ++ } else { + p->prio = current->prio; + list_add_tail(&p->run_list, ¤t->run_list); +- p->array = current->array; +- p->array->nr_active++; + rq->nr_running++; + } + set_need_resched(); +- } else ++ } else { + /* Run child last */ +- __activate_task(p, rq); +- /* +- * We skip the following code due to cpu == this_cpu +- * +- * task_rq_unlock(rq, &flags); +- * this_rq = task_rq_lock(current, &flags); +- */ +- this_rq = rq; ++ p->prio = effective_prio(p); ++ __activate_task(p); ++ } + } else { +- this_rq = cpu_rq(this_cpu); +- +- /* +- * Not the local CPU - must adjust timestamp. This should +- * get optimised away in the !CONFIG_SMP case. +- */ +- p->timestamp = (p->timestamp - this_rq->timestamp_last_tick) +- + rq->timestamp_last_tick; +- __activate_task(p, rq); +- if (TASK_PREEMPTS_CURR(p, rq)) +- resched_task(rq->curr); +- ++ p->prio = effective_prio(p); ++ __activate_task(p); ++ preempt_curr_if_warranted(p); + schedstat_inc(rq, wunt_moved); +- /* +- * Parent and child are on different CPUs, now get the +- * parent runqueue to update the parent's ->sleep_avg: +- */ +- task_rq_unlock(rq, &flags); +- this_rq = task_rq_lock(current, &flags); + } +- current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) * +- PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS); +- task_rq_unlock(this_rq, &flags); ++ task_rq_unlock(rq, &flags); + } + +-/* +- * Potentially available exiting-child timeslices are +- * retrieved here - this way the parent does not get +- * penalized for creating too many threads. +- * +- * (this cannot be used to 'generate' timeslices +- * artificially, because any timeslice recovered here +- * was given away by the parent in the first place.) ++/** ++ * No more timeslice fiddling on exit ++ * (Optionally) log scheduler statistics at exit. + */ ++static int log_at_exit = 0; + void fastcall sched_exit(task_t * p) + { +- unsigned long flags; +- runqueue_t *rq; ++ struct task_cpustats stats; + +- /* +- * If the child was a (relative-) CPU hog then decrease +- * the sleep_avg of the parent as well. +- */ +- rq = task_rq_lock(p->parent, &flags); +- if (p->first_time_slice) { +- p->parent->time_slice += p->time_slice; +- if (unlikely(p->parent->time_slice > task_timeslice(p))) +- p->parent->time_slice = task_timeslice(p); +- } +- if (p->sleep_avg < p->parent->sleep_avg) +- p->parent->sleep_avg = p->parent->sleep_avg / +- (EXIT_WEIGHT + 1) * EXIT_WEIGHT + p->sleep_avg / +- (EXIT_WEIGHT + 1); +- task_rq_unlock(rq, &flags); ++ if (!log_at_exit) ++ return; ++ ++ get_task_cpustats(p, &stats); ++ printk("SCHED_EXIT[%d] (%s) %llu %llu %llu %llu %llu %llu %lu %lu\n", ++ p->pid, p->comm, ++ stats.total_sleep, stats.total_cpu, stats.total_delay, ++ stats.total_sinbin, stats.total_wake_ups, stats.intr_wake_ups, ++ p->nvcsw, p->nivcsw); + } + + /** +@@ -1626,30 +1554,25 @@ + * Both runqueues must be locked. + */ + static inline +-void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p, +- runqueue_t *this_rq, prio_array_t *this_array, int this_cpu) ++void pull_task(task_t *p, int this_cpu) + { +- dequeue_task(p, src_array); ++ runqueue_t *src_rq = task_rq(p), *this_rq; ++ ++ dequeue_task(p); + src_rq->nr_running--; ++ delta_delay_cpustats(p, adjusted_sched_clock(p)); + set_task_cpu(p, this_cpu); ++ this_rq = task_rq(p); + this_rq->nr_running++; +- enqueue_task(p, this_array); +- p->timestamp = (p->timestamp - src_rq->timestamp_last_tick) +- + this_rq->timestamp_last_tick; +- /* +- * Note that idle threads have a prio of MAX_PRIO, for this test +- * to be always true for them. +- */ +- if (TASK_PREEMPTS_CURR(p, this_rq)) +- resched_task(this_rq->curr); ++ enqueue_task(p); ++ preempt_curr_if_warranted(p); + } + + /* + * can_migrate_task - may task p from runqueue rq be migrated to this_cpu? + */ + static inline +-int can_migrate_task(task_t *p, runqueue_t *rq, int this_cpu, +- struct sched_domain *sd, enum idle_type idle) ++int can_migrate_task(task_t *p, int this_cpu, struct sched_domain *sd, enum idle_type idle) + { + /* + * We do not migrate tasks that are: +@@ -1657,7 +1580,7 @@ + * 2) cannot be migrated to this CPU due to cpus_allowed, or + * 3) are cache-hot on their current CPU. + */ +- if (task_running(rq, p)) ++ if (task_is_running(p)) + return 0; + if (!cpu_isset(this_cpu, p->cpus_allowed)) + return 0; +@@ -1672,7 +1595,7 @@ + sd->nr_balance_failed > sd->cache_nice_tries) + return 1; + +- if (task_hot(p, rq->timestamp_last_tick, sd)) ++ if (task_hot(p, p->rq->timestamp_last_tick, sd)) + return 0; + return 1; + } +@@ -1688,7 +1611,6 @@ + unsigned long max_nr_move, struct sched_domain *sd, + enum idle_type idle) + { +- prio_array_t *array, *dst_array; + struct list_head *head, *curr; + int idx, pulled = 0; + task_t *tmp; +@@ -1696,45 +1618,26 @@ + if (max_nr_move <= 0 || busiest->nr_running <= 1) + goto out; + +- /* +- * We first consider expired tasks. Those will likely not be +- * executed in the near future, and they are most likely to +- * be cache-cold, thus switching CPUs has the least effect +- * on them. +- */ +- if (busiest->expired->nr_active) { +- array = busiest->expired; +- dst_array = this_rq->expired; +- } else { +- array = busiest->active; +- dst_array = this_rq->active; +- } +- +-new_array: + /* Start searching at priority 0: */ + idx = 0; + skip_bitmap: + if (!idx) +- idx = sched_find_first_bit(array->bitmap); ++ idx = sched_find_first_bit(busiest->bitmap); + else +- idx = find_next_bit(array->bitmap, MAX_PRIO, idx); +- if (idx >= MAX_PRIO) { +- if (array == busiest->expired && busiest->active->nr_active) { +- array = busiest->active; +- dst_array = this_rq->active; +- goto new_array; +- } ++ idx = find_next_bit(busiest->bitmap, IDLE_PRIO, idx); ++ if (idx >= IDLE_PRIO) + goto out; +- } + +- head = array->queue + idx; ++ head = &busiest->queues[idx].queue; + curr = head->prev; + skip_queue: + tmp = list_entry(curr, task_t, run_list); ++ /* take the opportunity to update tmp's prio field */ ++ tmp->prio = idx; + + curr = curr->prev; + +- if (!can_migrate_task(tmp, busiest, this_cpu, sd, idle)) { ++ if (!can_migrate_task(tmp, this_cpu, sd, idle)) { + if (curr != head) + goto skip_queue; + idx++; +@@ -1749,7 +1652,7 @@ + schedstat_inc(this_rq, pt_gained[idle]); + schedstat_inc(busiest, pt_lost[idle]); + +- pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu); ++ pull_task(tmp, this_cpu); + pulled++; + + /* We only want to steal up to the prescribed number of tasks. */ +@@ -2220,8 +2123,9 @@ + + static inline int wake_priority_sleeper(runqueue_t *rq) + { +- int ret = 0; + #ifdef CONFIG_SCHED_SMT ++ int ret = 0; ++ + spin_lock(&rq->lock); + /* + * If an SMT sibling task has been put to sleep for priority +@@ -2232,8 +2136,11 @@ + ret = 1; + } + spin_unlock(&rq->lock); +-#endif ++ + return ret; ++#else ++ return 0; ++#endif + } + + DEFINE_PER_CPU(struct kernel_stat, kstat); +@@ -2241,22 +2148,6 @@ + EXPORT_PER_CPU_SYMBOL(kstat); + + /* +- * We place interactive tasks back into the active array, if possible. +- * +- * To guarantee that this does not starve expired tasks we ignore the +- * interactivity of a task if the first expired task had to wait more +- * than a 'reasonable' amount of time. This deadline timeout is +- * load-dependent, as the frequency of array switched decreases with +- * increasing number of running tasks. We also ignore the interactivity +- * if a better static_prio task has expired: +- */ +-#define EXPIRED_STARVING(rq) \ +- ((STARVATION_LIMIT && ((rq)->expired_timestamp && \ +- (jiffies - (rq)->expired_timestamp >= \ +- STARVATION_LIMIT * ((rq)->nr_running) + 1))) || \ +- ((rq)->curr->static_prio > (rq)->best_expired_prio)) +- +-/* + * Do the virtual cpu time signal calculations. + * @p: the process that the cpu time gets accounted to + * @cputime: the cpu time spent in user space since the last update +@@ -2416,6 +2307,8 @@ + task_t *p = current; + + rq->timestamp_last_tick = sched_clock(); ++ tick_runq_cpustats(p->csrq, rq->timestamp_last_tick); ++ zaphod_runq_data_tick(p->zrq, rq->nr_running); + + if (p == rq->idle) { + if (wake_priority_sleeper(rq)) +@@ -2424,79 +2317,34 @@ + return; + } + +- /* Task might have expired already, but not scheduled off yet */ +- if (p->array != rq->active) { +- set_tsk_need_resched(p); ++ /* ++ * FIFO tasks have no timeslices. ++ */ ++ if (unlikely(p->policy == SCHED_FIFO)) + goto out; +- } ++ + spin_lock(&rq->lock); + /* +- * The task was running during this tick - update the +- * time slice counter. Note: we do not update a thread's +- * priority until it either goes to sleep or uses up its +- * timeslice. This makes it possible for interactive tasks +- * to use up their timeslices at their highest priority levels. ++ * The task was running during this tick + */ +- if (rt_task(p)) { +- /* +- * RR tasks need a special form of timeslice management. +- * FIFO tasks have no timeslices. +- */ +- if ((p->policy == SCHED_RR) && !--p->time_slice) { +- p->time_slice = task_timeslice(p); +- p->first_time_slice = 0; +- set_tsk_need_resched(p); +- +- /* put it at the end of the queue: */ +- requeue_task(p, rq->active); +- } +- goto out_unlock; +- } + if (!--p->time_slice) { +- dequeue_task(p, rq->active); ++ dequeue_task(p); + set_tsk_need_resched(p); +- p->prio = effective_prio(p); +- p->time_slice = task_timeslice(p); +- p->first_time_slice = 0; +- +- if (!rq->expired_timestamp) +- rq->expired_timestamp = jiffies; +- if (!TASK_INTERACTIVE(p) || EXPIRED_STARVING(rq)) { +- enqueue_task(p, rq->expired); +- if (p->static_prio < rq->best_expired_prio) +- rq->best_expired_prio = p->static_prio; +- } else +- enqueue_task(p, rq->active); +- } else { +- /* +- * Prevent a too long timeslice allowing a task to monopolize +- * the CPU. We do this by splitting up the timeslice into +- * smaller pieces. +- * +- * Note: this does not mean the task's timeslices expire or +- * get lost in any way, they just might be preempted by +- * another task of equal priority. (one with higher +- * priority would have preempted this task already.) We +- * requeue this task to the end of the list on this priority +- * level, which is in essence a round-robin of tasks with +- * equal priority. +- * +- * This only applies to tasks in the interactive +- * delta range with at least TIMESLICE_GRANULARITY to requeue. +- */ +- if (TASK_INTERACTIVE(p) && !((task_timeslice(p) - +- p->time_slice) % TIMESLICE_GRANULARITY(p)) && +- (p->time_slice >= TIMESLICE_GRANULARITY(p)) && +- (p->array == rq->active)) { +- +- requeue_task(p, rq->active); +- set_tsk_need_resched(p); +- } ++ update_cpustats_at_end_of_ts(p, rq->timestamp_last_tick); ++ if (unlikely(p->policy == SCHED_RR)) ++ p->time_slice = sched_rr_time_slice; ++ else { ++ zaphod_reassess_at_end_of_ts(p); ++ p->prio = effective_prio(p); ++ p->time_slice = task_timeslice(p); ++ } ++ enqueue_task(p); + } +-out_unlock: + spin_unlock(&rq->lock); + out: + rebalance_tick(cpu, rq, NOT_IDLE); ++ if (unlikely(promotions_due(rq))) ++ do_promotions(rq); + } + + #ifdef CONFIG_SCHED_SMT +@@ -2545,12 +2393,33 @@ + */ + } + ++/* maximum expected priority difference for SCHED_NORMAL tasks */ ++#define MAX_SN_PD (IDLE_PRIO - MIN_NORMAL_PRIO) ++static inline int dependent_sleeper_trumps(const task_t *p1, ++ const task_t * p2, unsigned int rq_percent_ts_rm) ++{ ++ int dp = p2->prio - p1->prio; ++ ++ if ((dp > 0) && (rq_percent_ts_rm < 100) && p2->mm && !rt_task(p2)) { ++ unsigned long rq_ts_rm; ++ ++ if (rt_task(p1)) ++ return 1; ++ ++ rq_ts_rm = ((MAX_SN_PD - dp) * time_slice * rq_percent_ts_rm) / ++ (100 * MAX_SN_PD); ++ ++ return p1->time_slice > rq_ts_rm; ++ } ++ ++ return 0; ++} ++ + static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq) + { + struct sched_domain *sd = this_rq->sd; + cpumask_t sibling_map; +- prio_array_t *array; +- int ret = 0, i; ++ int ret = 0, i, idx; + task_t *p; + + if (!(sd->flags & SD_SHARE_CPUPOWER)) +@@ -2572,13 +2441,11 @@ + */ + if (!this_rq->nr_running) + goto out_unlock; +- array = this_rq->active; +- if (!array->nr_active) +- array = this_rq->expired; +- BUG_ON(!array->nr_active); + +- p = list_entry(array->queue[sched_find_first_bit(array->bitmap)].next, +- task_t, run_list); ++ idx = sched_find_first_bit(this_rq->bitmap); ++ p = list_entry(this_rq->queues[idx].queue.next, task_t, run_list); ++ /* take the opportunity to update p's prio field */ ++ p->prio = idx; + + for_each_cpu_mask(i, sibling_map) { + runqueue_t *smt_rq = cpu_rq(i); +@@ -2592,9 +2459,7 @@ + * task from using an unfair proportion of the + * physical cpu's resources. -ck + */ +- if (((smt_curr->time_slice * (100 - sd->per_cpu_gain) / 100) > +- task_timeslice(p) || rt_task(smt_curr)) && +- p->mm && smt_curr->mm && !rt_task(p)) ++ if (dependent_sleeper_trumps(smt_curr, p, sd->per_cpu_gain)) + ret = 1; + + /* +@@ -2602,9 +2467,7 @@ + * or wake it up if it has been put to sleep for priority + * reasons. + */ +- if ((((p->time_slice * (100 - sd->per_cpu_gain) / 100) > +- task_timeslice(smt_curr) || rt_task(p)) && +- smt_curr->mm && p->mm && !rt_task(smt_curr)) || ++ if (dependent_sleeper_trumps(p, smt_curr, sd->per_cpu_gain) || + (smt_curr == smt_rq->idle && smt_rq->nr_running)) + resched_task(smt_curr); + } +@@ -2664,10 +2527,8 @@ + long *switch_count; + task_t *prev, *next; + runqueue_t *rq; +- prio_array_t *array; + struct list_head *queue; + unsigned long long now; +- unsigned long run_time; + int cpu, idx; + + /* +@@ -2703,16 +2564,6 @@ + + schedstat_inc(rq, sched_cnt); + now = sched_clock(); +- if (likely(now - prev->timestamp < NS_MAX_SLEEP_AVG)) +- run_time = now - prev->timestamp; +- else +- run_time = NS_MAX_SLEEP_AVG; +- +- /* +- * Tasks charged proportionately less run_time at high sleep_avg to +- * delay them losing their interactive status +- */ +- run_time /= (CURRENT_BONUS(prev) ? : 1); + + spin_lock_irq(&rq->lock); + +@@ -2728,17 +2579,20 @@ + else { + if (prev->state == TASK_UNINTERRUPTIBLE) + rq->nr_uninterruptible++; +- deactivate_task(prev, rq); ++ deactivate_task(prev); + } + } + ++ delta_cpu_cpustats(prev, now); ++ if (task_needs_sinbinning(prev) && !signal_pending(prev)) ++ put_task_in_sinbin(prev, required_sinbin_durn(prev)); ++ + cpu = smp_processor_id(); + if (unlikely(!rq->nr_running)) { + go_idle: + idle_balance(cpu, rq); + if (!rq->nr_running) { + next = rq->idle; +- rq->expired_timestamp = 0; + wake_sleeping_dependent(cpu, rq); + /* + * wake_sleeping_dependent() might have released +@@ -2762,36 +2616,13 @@ + goto go_idle; + } + +- array = rq->active; +- if (unlikely(!array->nr_active)) { +- /* +- * Switch the active and expired arrays. +- */ +- schedstat_inc(rq, sched_switch); +- rq->active = rq->expired; +- rq->expired = array; +- array = rq->active; +- rq->expired_timestamp = 0; +- rq->best_expired_prio = MAX_PRIO; +- } else +- schedstat_inc(rq, sched_noswitch); ++ schedstat_inc(rq, sched_noswitch); + +- idx = sched_find_first_bit(array->bitmap); +- queue = array->queue + idx; ++ idx = sched_find_first_bit(rq->bitmap); ++ queue = &rq->queues[idx].queue; + next = list_entry(queue->next, task_t, run_list); +- +- if (!rt_task(next) && next->activated > 0) { +- unsigned long long delta = now - next->timestamp; +- +- if (next->activated == 1) +- delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128; +- +- array = next->array; +- dequeue_task(next, array); +- recalc_task_prio(next, next->timestamp + delta); +- enqueue_task(next, array); +- } +- next->activated = 0; ++ /* take the opportunity to update next's prio field */ ++ next->prio = idx; + switch_tasks: + if (next == rq->idle) + schedstat_inc(rq, sched_goidle); +@@ -2799,14 +2630,11 @@ + clear_tsk_need_resched(prev); + rcu_qsctr_inc(task_cpu(prev)); + +- prev->sleep_avg -= run_time; +- if ((long)prev->sleep_avg <= 0) +- prev->sleep_avg = 0; +- prev->timestamp = prev->last_ran = now; ++ prev->last_ran = now; + + sched_info_switch(prev, next); + if (likely(prev != next)) { +- next->timestamp = now; ++ delta_delay_cpustats(next, now); + rq->nr_switches++; + rq->curr = next; + ++*switch_count; +@@ -3227,9 +3055,7 @@ + void set_user_nice(task_t *p, long nice) + { + unsigned long flags; +- prio_array_t *array; + runqueue_t *rq; +- int old_prio, new_prio, delta; + + if (TASK_NICE(p) == nice || nice < -20 || nice > 19) + return; +@@ -3238,36 +3064,31 @@ + * the task might be in the middle of scheduling on another CPU. + */ + rq = task_rq_lock(p, &flags); ++ ++ p->static_prio = NICE_TO_PRIO(nice); ++ zaphod_reassess_at_renice(p); + /* + * The RT priorities are set via sched_setscheduler(), but we still + * allow the 'normal' nice value to be set - but as expected + * it wont have any effect on scheduling until the task is + * not SCHED_NORMAL: ++ * There's no need to set "prio" if the task isn't queued as it will ++ * get set during activation. + */ +- if (rt_task(p)) { +- p->static_prio = NICE_TO_PRIO(nice); +- goto out_unlock; +- } +- array = p->array; +- if (array) +- dequeue_task(p, array); +- +- old_prio = p->prio; +- new_prio = NICE_TO_PRIO(nice); +- delta = new_prio - old_prio; +- p->static_prio = NICE_TO_PRIO(nice); +- p->prio += delta; ++ if (!rt_task(p) && task_queued(p)) { ++ int delta = -p->prio; + +- if (array) { +- enqueue_task(p, array); ++ dequeue_task(p); ++ delta += (p->prio = effective_prio(p)); ++ enqueue_task(p); + /* + * If the task increased its priority or is running and + * lowered its priority, then reschedule its CPU: + */ +- if (delta < 0 || (delta > 0 && task_running(rq, p))) ++ if (delta < 0 || (delta > 0 && task_is_running(p))) + resched_task(rq->curr); + } +-out_unlock: ++ + task_rq_unlock(rq, &flags); + } + +@@ -3317,6 +3138,116 @@ + + #endif + ++/* ++ * Require: 0 <= new_cap <= 1000 ++ */ ++int set_cpu_rate_cap(struct task_struct *p, unsigned long new_cap) ++{ ++ int is_allowed; ++ unsigned long flags; ++ runqueue_t *rq; ++ long delta; ++ ++ if (new_cap > 1000) ++ return -EINVAL; ++ is_allowed = capable(CAP_SYS_NICE); ++ /* ++ * We have to be careful, if called from /proc code, ++ * the task might be in the middle of scheduling on another CPU. ++ */ ++ new_cap = ppt_to_proportion(new_cap); ++ rq = task_rq_lock(p, &flags); ++ delta = new_cap - p->cpu_rate_cap; ++ if (!is_allowed) { ++ /* ++ * Ordinary users can set/change caps on their own tasks ++ * provided that the new setting is MORE constraining ++ */ ++ if (((current->euid != p->uid) && (current->uid != p->uid)) || (delta > 0)) { ++ task_rq_unlock(rq, &flags); ++ return -EPERM; ++ } ++ } ++ /* ++ * The RT tasks don't have caps, but we still allow the caps to be ++ * set - but as expected it wont have any effect on scheduling until ++ * the task becomes SCHED_NORMAL: ++ */ ++ p->cpu_rate_cap = new_cap; ++ if (p->cpu_rate_cap < p->cpu_rate_hard_cap) ++ p->min_cpu_rate_cap = p->cpu_rate_cap; ++ else ++ p->min_cpu_rate_cap = p->cpu_rate_hard_cap; ++ zaphod_reassess_at_renice(p); ++ if (!rt_task(p) && task_queued(p)) { ++ int delta = -p->prio; ++ ++ dequeue_task(p); ++ delta += p->prio = effective_prio(p); ++ enqueue_task(p); ++ /* ++ * If the task increased its priority or is running and ++ * lowered its priority, then reschedule its CPU: ++ */ ++ if (delta < 0 || (delta > 0 && task_is_running(p))) ++ resched_task(rq->curr); ++ } ++ task_rq_unlock(rq, &flags); ++ return 0; ++} ++ ++EXPORT_SYMBOL(set_cpu_rate_cap); ++ ++/* ++ * Require: 1 <= new_cap <= 1000 ++ */ ++int set_cpu_rate_hard_cap(struct task_struct *p, unsigned long new_cap) ++{ ++ int is_allowed; ++ unsigned long flags; ++ runqueue_t *rq; ++ long delta; ++ ++ if ((new_cap > 1000) || (new_cap == 0)) /* zero hard caps are not allowed */ ++ return -EINVAL; ++ is_allowed = capable(CAP_SYS_NICE); ++ new_cap = ppt_to_proportion(new_cap); ++ /* ++ * We have to be careful, if called from /proc code, ++ * the task might be in the middle of scheduling on another CPU. ++ */ ++ rq = task_rq_lock(p, &flags); ++ delta = new_cap - p->cpu_rate_hard_cap; ++ if (!is_allowed) { ++ /* ++ * Ordinary users can set/change caps on their own tasks ++ * provided that the new setting is MORE constraining ++ */ ++ if (((current->euid != p->uid) && (current->uid != p->uid)) || (delta > 0)) { ++ task_rq_unlock(rq, &flags); ++ return -EPERM; ++ } ++ } ++ /* ++ * The RT tasks don't have caps, but we still allow the caps to be ++ * set - but as expected it wont have any effect on scheduling until ++ * the task becomes SCHED_NORMAL: ++ */ ++ p->cpu_rate_hard_cap = new_cap; ++ if (p->cpu_rate_cap < p->cpu_rate_hard_cap) ++ p->min_cpu_rate_cap = p->cpu_rate_cap; ++ else ++ p->min_cpu_rate_cap = p->cpu_rate_hard_cap; ++ zaphod_reassess_at_renice(p); ++ /* (POSSIBLY) TODO: if it's sinbinned and the cap is relaxed then ++ * release it from the sinbin ++ */ ++ task_rq_unlock(rq, &flags); ++ return 0; ++} ++ ++EXPORT_SYMBOL(set_cpu_rate_hard_cap); ++ + /** + * task_prio - return the priority value of a given task. + * @p: the task in question. +@@ -3380,7 +3311,7 @@ + /* Actually do priority change: must hold rq lock. */ + static void __setscheduler(struct task_struct *p, int policy, int prio) + { +- BUG_ON(p->array); ++ BUG_ON(task_queued(p)); + p->policy = policy; + p->rt_priority = prio; + if (policy != SCHED_NORMAL) +@@ -3400,7 +3331,7 @@ + { + int retval; + int oldprio, oldpolicy = -1; +- prio_array_t *array; ++ int queued; + unsigned long flags; + runqueue_t *rq; + +@@ -3422,8 +3353,14 @@ + return -EINVAL; + + if ((policy == SCHED_FIFO || policy == SCHED_RR) && +- !capable(CAP_SYS_NICE)) ++ !capable(CAP_SYS_NICE)) { ++ if (current->euid == p->uid) { ++ rq = task_rq_lock(p, &flags); ++ p->flags |= PF_UNPRIV_RT; ++ task_rq_unlock(rq, &flags); ++ } + return -EPERM; ++ } + if ((current->euid != p->euid) && (current->euid != p->uid) && + !capable(CAP_SYS_NICE)) + return -EPERM; +@@ -3442,23 +3379,23 @@ + task_rq_unlock(rq, &flags); + goto recheck; + } +- array = p->array; +- if (array) +- deactivate_task(p, rq); ++ queued = task_queued(p); ++ if (queued) ++ deactivate_task(p); + oldprio = p->prio; + __setscheduler(p, policy, param->sched_priority); +- if (array) { +- __activate_task(p, rq); ++ if (queued) { ++ __activate_task(p); + /* + * Reschedule if we are currently running on this runqueue and + * our priority decreased, or if we are not currently running on + * this runqueue and our priority is higher than the current's + */ +- if (task_running(rq, p)) { ++ if (task_is_running(p)) { + if (p->prio > oldprio) + resched_task(rq->curr); +- } else if (TASK_PREEMPTS_CURR(p, rq)) +- resched_task(rq->curr); ++ } else ++ preempt_curr_if_warranted(p); + } + task_rq_unlock(rq, &flags); + return 0; +@@ -3705,6 +3642,96 @@ + return sizeof(cpumask_t); + } + ++int get_task_cpustats(struct task_struct *tsk, struct task_cpustats *stats) ++{ ++ int on_runq = 0; ++ int on_cpu = 0; ++ unsigned long long timestamp = 0; ++ unsigned long flags; ++ runqueue_t *rq = task_rq_lock(tsk, &flags); ++ ++ *stats = tsk->cpustats; ++#ifdef CONFIG_SMP ++ timestamp = tsk->csrq->timestamp_last_tick; ++#endif ++ if ((on_runq = task_queued(tsk))) ++ on_cpu = task_is_running(tsk); ++ ++ task_rq_unlock(rq, &flags); ++ ++ /* ++ * Update values to the previous tick (only) ++ */ ++ if (timestamp > stats->timestamp) { ++ unsigned long long delta = timestamp - stats->timestamp; ++ ++ stats->timestamp = timestamp; ++ if (on_cpu) { ++ stats->total_cpu += delta; ++ } else if (on_runq) { ++ stats->total_delay += delta; ++ } else { ++ stats->total_sleep += delta; ++ } ++ } ++ ++ return 0; ++} ++ ++EXPORT_SYMBOL(get_task_cpustats); ++ ++/* ++ * Get scheduling statistics for the nominated CPU ++ */ ++int get_cpu_cpustats(unsigned int cpu, struct cpu_cpustats *stats) ++{ ++ int idle; ++ unsigned long long idle_timestamp; ++ runqueue_t *rq = cpu_rq(cpu); ++ struct runq_cpustats *csrq = cpu_runq_cpustats(cpu); ++ /* ++ * No need to crash the whole machine if they've asked for stats for ++ * a non existent CPU. ++ */ ++ if (rq == NULL) ++ return -EFAULT; ++ ++ local_irq_disable(); ++ spin_lock(&rq->lock); ++ idle = rq->curr == rq->idle; ++#ifdef CONFIG_SMP ++ if (csrq->timestamp_last_tick > rq->curr->cpustats.timestamp) ++ stats->timestamp = csrq->timestamp_last_tick; ++ else ++#endif ++ stats->timestamp = rq->curr->cpustats.timestamp; ++ idle_timestamp = rq->idle->cpustats.timestamp; ++ if (idle_timestamp > stats->timestamp) ++ stats->timestamp = idle_timestamp; ++ stats->total_idle = rq->idle->cpustats.total_cpu; ++ stats->total_busy = rq->idle->cpustats.total_delay; ++ stats->total_delay = csrq->total_delay; ++ stats->total_rt_delay = csrq->total_rt_delay; ++ stats->total_intr_delay = csrq->total_intr_delay; ++ stats->total_rt_intr_delay = csrq->total_rt_intr_delay; ++ stats->total_fork_delay = csrq->total_fork_delay; ++ stats->total_sinbin = csrq->total_sinbin; ++ stats->nr_switches = rq->nr_switches; ++ spin_unlock_irq(&rq->lock); ++ ++ /* ++ * Update idle/busy time to the current tick ++ */ ++ if (idle) ++ stats->total_idle += (stats->timestamp - idle_timestamp); ++ else ++ stats->total_busy += (stats->timestamp - idle_timestamp); ++ ++ return 0; ++} ++ ++EXPORT_SYMBOL(get_cpu_cpustats); ++ + /** + * sys_sched_yield - yield the current processor to other threads. + * +@@ -3715,35 +3742,30 @@ + asmlinkage long sys_sched_yield(void) + { + runqueue_t *rq = this_rq_lock(); +- prio_array_t *array = current->array; +- prio_array_t *target = rq->expired; + + schedstat_inc(rq, yld_cnt); +- /* +- * We implement yielding by moving the task into the expired +- * queue. +- * +- * (special rule: RT tasks will just roundrobin in the active +- * array.) +- */ +- if (rt_task(current)) +- target = rq->active; +- +- if (current->array->nr_active == 1) { +- schedstat_inc(rq, yld_act_empty); +- if (!rq->expired->nr_active) +- schedstat_inc(rq, yld_both_empty); +- } else if (!rq->expired->nr_active) +- schedstat_inc(rq, yld_exp_empty); +- +- if (array != target) { +- dequeue_task(current, array); +- enqueue_task(current, target); +- } else +- /* +- * requeue_task is cheaper so perform that if possible. +- */ +- requeue_task(current, array); ++ /* If there's other tasks on this CPU make sure that at least ++ * one of them get some CPU before this task's next bite of the ++ * cherry. Dequeue before looking for the appropriate run ++ * queue so that we don't find our queue if we were the sole ++ * occupant of that queue. ++ */ ++ dequeue_task(current); ++ /* ++ * special rule: RT tasks will just roundrobin. ++ */ ++ if (likely(!rt_task(current))) { ++ int idx = find_next_bit(rq->bitmap, IDLE_PRIO, current->prio); ++ if (idx < IDLE_PRIO) { ++ if ((idx < BGND_PRIO) || task_is_bgnd(current)) ++ current->prio = idx; ++ else ++ current->prio = BGND_PRIO - 1; ++ } ++ } ++ enqueue_task(current); ++ if (rq->nr_running == 1) ++ schedstat_inc(rq, yld_both_empty); + + /* + * Since we are going to call schedule() anyway, there's +@@ -4054,9 +4076,14 @@ + runqueue_t *rq = cpu_rq(cpu); + unsigned long flags; + +- idle->sleep_avg = 0; +- idle->array = NULL; +- idle->prio = MAX_PRIO; ++ idle->prio = IDLE_PRIO; ++ /* ++ * Initialize scheduling statistics counters as they may provide ++ * valuable about the CPU e.g. avg_cpu_time_per_cycle for the idle ++ * task will be an estimate of the average time the CPU is idle. ++ * sched_init() may not be ready so use INITIAL_JIFFIES instead. ++ */ ++ initialize_cpustats(idle, INITIAL_CPUSTATS_TIMESTAMP); + idle->state = TASK_RUNNING; + set_task_cpu(idle, cpu); + +@@ -4153,6 +4180,7 @@ + static void __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu) + { + runqueue_t *rq_dest, *rq_src; ++ unsigned long long now; + + if (unlikely(cpu_is_offline(dest_cpu))) + return; +@@ -4168,20 +4196,17 @@ + if (!cpu_isset(dest_cpu, p->cpus_allowed)) + goto out; + +- set_task_cpu(p, dest_cpu); +- if (p->array) { +- /* +- * Sync timestamp with rq_dest's before activating. +- * The same thing could be achieved by doing this step +- * afterwards, and pretending it was a local activate. +- * This way is cleaner and logically correct. +- */ +- p->timestamp = p->timestamp - rq_src->timestamp_last_tick +- + rq_dest->timestamp_last_tick; +- deactivate_task(p, rq_src); +- activate_task(p, rq_dest, 0); +- if (TASK_PREEMPTS_CURR(p, rq_dest)) +- resched_task(rq_dest->curr); ++ now = adjusted_sched_clock(p); ++ if (task_queued(p)) { ++ deactivate_task(p); ++ /* not the current task on its cpu so increment delay stats */ ++ delta_delay_cpustats(p, now); ++ set_task_cpu(p, dest_cpu); ++ activate_task(p); ++ preempt_curr_if_warranted(p); ++ } else { ++ delta_sleep_cpustats(p, now); ++ set_task_cpu(p, dest_cpu); + } + + out: +@@ -4353,7 +4378,7 @@ + + __setscheduler(p, SCHED_FIFO, MAX_RT_PRIO-1); + /* Add idle task to _front_ of it's priority queue */ +- __activate_idle_task(p, rq); ++ __activate_idle_task(rq); + + spin_unlock_irqrestore(&rq->lock, flags); + } +@@ -4399,18 +4424,16 @@ + /* release_task() removes task from tasklist, so we won't find dead tasks. */ + static void migrate_dead_tasks(unsigned int dead_cpu) + { +- unsigned arr, i; ++ unsigned i; + struct runqueue *rq = cpu_rq(dead_cpu); + +- for (arr = 0; arr < 2; arr++) { +- for (i = 0; i < MAX_PRIO; i++) { +- struct list_head *list = &rq->arrays[arr].queue[i]; +- while (!list_empty(list)) +- migrate_dead(dead_cpu, +- list_entry(list->next, task_t, +- run_list)); +- } ++ for (i = 0; i < IDLE_PRIO; i++) { ++ struct list_head *list = &rq->queues[i].queue; ++ while (!list_empty(list)) ++ migrate_dead(dead_cpu, list_entry(list->next, task_t, run_list)); + } ++ ++ return 0; + } + #endif /* CONFIG_HOTPLUG_CPU */ + +@@ -4457,8 +4480,8 @@ + rq->migration_thread = NULL; + /* Idle task back to normal (off runqueue, low prio) */ + rq = task_rq_lock(rq->idle, &flags); +- deactivate_task(rq->idle, rq); +- rq->idle->static_prio = MAX_PRIO; ++ deactivate_task(rq->idle); ++ rq->idle->static_prio = IDLE_PRIO; + __setscheduler(rq->idle, SCHED_NORMAL, 0); + migrate_dead_tasks(cpu); + task_rq_unlock(rq, &flags); +@@ -4952,16 +4975,11 @@ + void __init sched_init(void) + { + runqueue_t *rq; +- int i, j, k; ++ int i, k, cpu; + + for (i = 0; i < NR_CPUS; i++) { +- prio_array_t *array; +- + rq = cpu_rq(i); + spin_lock_init(&rq->lock); +- rq->active = rq->arrays; +- rq->expired = rq->arrays + 1; +- rq->best_expired_prio = MAX_PRIO; + + #ifdef CONFIG_SMP + rq->sd = &sched_domain_dummy; +@@ -4973,17 +4991,26 @@ + #endif + atomic_set(&rq->nr_iowait, 0); + +- for (j = 0; j < 2; j++) { +- array = rq->arrays + j; +- for (k = 0; k < MAX_PRIO; k++) { +- INIT_LIST_HEAD(array->queue + k); +- __clear_bit(k, array->bitmap); +- } +- // delimiter for bitsearch +- __set_bit(MAX_PRIO, array->bitmap); ++ for (k = 0; k < IDLE_PRIO; k++) { ++ rq->queues[k].prio = k; ++ INIT_LIST_HEAD(&rq->queues[k].queue); + } ++ ++ bitmap_zero(rq->bitmap, NUM_PRIO_SLOTS); ++ /* delimiter for bitsearch */ ++ __set_bit(IDLE_PRIO, rq->bitmap); ++ init_runq_cpustats(i); ++ zaphod_init_cpu_runq_data(i); ++ rq->next_prom_due = ULONG_MAX; ++ rq->pcount = 0; + } + ++ cpu = smp_processor_id(); ++ /* make sure that these get set on single CPU systems */ ++ current->csrq = cpu_runq_cpustats(cpu); ++ current->zrq = zaphod_cpu_runq_data(cpu); ++ current->rq = cpu_rq(cpu); ++ + /* + * The boot idle thread does lazy MMU switching as well: + */ +@@ -4996,7 +5023,7 @@ + * but because we are the idle thread, we just pick up running again + * when this runqueue becomes "idle". + */ +- init_idle(current, smp_processor_id()); ++ init_idle(current, cpu); + } + + #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP +@@ -5025,7 +5052,7 @@ + void normalize_rt_tasks(void) + { + struct task_struct *p; +- prio_array_t *array; ++ int queued; + unsigned long flags; + runqueue_t *rq; + +@@ -5036,12 +5063,12 @@ + + rq = task_rq_lock(p, &flags); + +- array = p->array; +- if (array) +- deactivate_task(p, task_rq(p)); ++ queued = task_queued(p); ++ if (queued) ++ deactivate_task(p); + __setscheduler(p, SCHED_NORMAL, 0); +- if (array) { +- __activate_task(p, task_rq(p)); ++ if (queued) { ++ __activate_task(p); + resched_task(rq->curr); + } + +@@ -5051,3 +5078,98 @@ + } + + #endif /* CONFIG_MAGIC_SYSRQ */ ++ ++#if defined(CONFIG_SYSCTL) ++/* ++ * CPU scheduler control via /proc/sys/cpusched/xxx ++ */ ++enum ++{ ++ CPU_SCHED_END_OF_LIST=0, ++ CPU_SCHED_LOG_AT_EXIT, ++ CPU_SCHED_TIME_SLICE, ++ CPU_SCHED_SCHED_RR_TIME_SLICE, ++ CPU_SCHED_BASE_PROMOTION_INTERVAL, ++ CPU_SCHED_UNPRIV_RT_THRESHOLD, ++ CPU_SCHED_BGND_TIME_SLICE_MULTIPLIER, ++ CPU_SCHED_ZAPHOD, ++}; ++ ++ ++static const unsigned int zero = 0; ++static const unsigned int one = 1; ++static const unsigned long min_time_slice = MIN_TIMESLICE; ++static const unsigned long max_time_slice = MAX_TIMESLICE; ++#define min_base_prom_interval min_time_slice ++static const unsigned long max_base_prom_interval = ULONG_MAX; ++ ++ctl_table cpu_sched_table[] = { ++ { ++ .ctl_name = CPU_SCHED_LOG_AT_EXIT, ++ .procname = "log_at_exit", ++ .data = &log_at_exit, ++ .maxlen = sizeof (unsigned int), ++ .mode = 0644, ++ .proc_handler = &proc_dointvec_minmax, ++ .extra1 = (void *)&zero, ++ .extra2 = (void *)&one ++ }, ++ { ++ .ctl_name = CPU_SCHED_TIME_SLICE, ++ .procname = "time_slice", ++ .data = &time_slice, ++ .maxlen = sizeof (unsigned long), ++ .mode = 0644, ++ .proc_handler = &proc_doulongvec_ms_jiffies_minmax, ++ .extra1 = (void *)&min_time_slice, ++ .extra2 = (void *)&max_time_slice ++ }, ++ { ++ .ctl_name = CPU_SCHED_SCHED_RR_TIME_SLICE, ++ .procname = "sched_rr_time_slice", ++ .data = &sched_rr_time_slice, ++ .maxlen = sizeof (unsigned long), ++ .mode = 0644, ++ .proc_handler = &proc_doulongvec_ms_jiffies_minmax, ++ .extra1 = (void *)&min_time_slice, ++ .extra2 = (void *)&max_time_slice ++ }, ++ { ++ .ctl_name = CPU_SCHED_BASE_PROMOTION_INTERVAL, ++ .procname = "base_promotion_interval", ++ .data = &base_prom_interval, ++ .maxlen = sizeof (unsigned long), ++ .mode = 0644, ++ .proc_handler = &proc_doulongvec_ms_jiffies_minmax, ++ .extra1 = (void *)&min_base_prom_interval, ++ .extra2 = (void *)&max_base_prom_interval ++ }, ++ { ++ .ctl_name = CPU_SCHED_UNPRIV_RT_THRESHOLD, ++ .procname = "unpriv_rt_threshold", ++ .data = &unpriv_rt_threshold, ++ .maxlen = sizeof (unsigned long), ++ .mode = 0644, ++ .proc_handler = &do_proc_proportion, ++ .extra1 = NULL, ++ .extra2 = NULL ++ }, ++ { ++ .ctl_name = CPU_SCHED_BGND_TIME_SLICE_MULTIPLIER, ++ .procname = "bgnd_time_slice_multiplier", ++ .data = &bgnd_time_slice_multiplier, ++ .maxlen = sizeof (unsigned int), ++ .mode = 0644, ++ .proc_handler = &proc_dointvec_minmax, ++ .extra1 = (void *)&one, ++ .extra2 = (void *)&max_bgnd_time_slice_multiplier ++ }, ++ { ++ .ctl_name = CPU_SCHED_ZAPHOD, ++ .procname = "zaphod", ++ .mode = 0555, ++ .child = zaphod_ctl_table, ++ }, ++ { .ctl_name = CPU_SCHED_END_OF_LIST } ++}; ++#endif +Index: 2.6.11/kernel/sched_cpustats.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ 2.6.11/kernel/sched_cpustats.c 2005-04-15 10:46:29.045185928 -0500 +@@ -0,0 +1,399 @@ ++/* ++ * kernel/sched_stats.c ++ * ++ * Kernel highe resolution cpu statistics for use by schedulers ++ * ++ * Copyright (C) 2004 Aurema Pty Ltd ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#include ++#include ++ ++static DEFINE_PER_CPU(struct runq_cpustats, cpustats_runqs); ++ ++void init_runq_cpustats(unsigned int cpu) ++{ ++ struct runq_cpustats *csrq = &per_cpu(cpustats_runqs, cpu); ++ ++ csrq->total_delay = 0; ++ csrq->total_sinbin = 0; ++ csrq->total_rt_delay = 0; ++ csrq->total_intr_delay = 0; ++ csrq->total_rt_intr_delay = 0; ++ csrq->total_fork_delay = 0; ++#ifdef CONFIG_SMP ++ csrq->timestamp_last_tick = INITIAL_CPUSTATS_TIMESTAMP; ++#endif ++} ++ ++#ifdef CONFIG_SMP ++unsigned long long adjusted_sched_clock(const task_t *p) ++{ ++ struct runq_cpustats *trq = &__get_cpu_var(cpustats_runqs); ++ ++ return sched_clock() + (RUNQ_CPUSTATS(p)->timestamp_last_tick - trq->timestamp_last_tick); ++} ++ ++void set_task_runq_cpustats(struct task_struct *p, unsigned int cpu) ++{ ++ unsigned long long oldts = RUNQ_CPUSTATS(p)->timestamp_last_tick; ++ ++ RUNQ_CPUSTATS(p) = cpu_runq_cpustats(cpu); ++ TASK_CPUSTATS(p).timestamp += (RUNQ_CPUSTATS(p)->timestamp_last_tick - oldts); ++} ++#endif ++ ++extern struct runq_cpustats *cpu_runq_cpustats(unsigned int cpu) ++{ ++ return &per_cpu(cpustats_runqs, cpu); ++} ++ ++void initialize_cpustats(struct task_struct *p, unsigned long long now) ++{ ++ TASK_CPUSTATS(p).avg_sleep_per_cycle = 0; ++ TASK_CPUSTATS(p).avg_delay_per_cycle = 0; ++ TASK_CPUSTATS(p).avg_cpu_per_cycle = 0; ++ TASK_CPUSTATS(p).total_sleep = 0; ++ TASK_CPUSTATS(p).total_delay = 0; ++ TASK_CPUSTATS(p).total_sinbin = 0; ++ TASK_CPUSTATS(p).total_cpu = 0; ++ TASK_CPUSTATS(p).total_wake_ups = 0; ++ TASK_CPUSTATS(p).intr_wake_ups = 0; ++ TASK_CPUSTATS(p).avg_cycle_length = 0; ++ TASK_CPUSTATS(p).timestamp = now; ++ TASK_CPUSTATS(p).flags = CPUSTATS_JUST_FORKED_FL; ++} ++ ++void delta_sleep_cpustats(struct task_struct *p, unsigned long long now) ++{ ++ unsigned long long delta; ++ ++ /* sched_clock() is not guaranteed monotonic */ ++ if (now <= TASK_CPUSTATS(p).timestamp) { ++ TASK_CPUSTATS(p).timestamp = now; ++ return; ++ } ++ ++ delta = now - TASK_CPUSTATS(p).timestamp; ++ TASK_CPUSTATS(p).timestamp = now; ++ TASK_CPUSTATS(p).avg_sleep_per_cycle += delta; ++ TASK_CPUSTATS(p).total_sleep += delta; ++} ++ ++void delta_cpu_cpustats(struct task_struct *p, unsigned long long now) ++{ ++ unsigned long long delta; ++ ++ /* sched_clock() is not guaranteed monotonic */ ++ if (now <= TASK_CPUSTATS(p).timestamp) { ++ TASK_CPUSTATS(p).timestamp = now; ++ return; ++ } ++ ++ delta = now - TASK_CPUSTATS(p).timestamp; ++ TASK_CPUSTATS(p).timestamp = now; ++ TASK_CPUSTATS(p).avg_cpu_per_cycle += delta; ++ TASK_CPUSTATS(p).total_cpu += delta; ++} ++ ++void delta_delay_cpustats(struct task_struct *p, unsigned long long now) ++{ ++ unsigned long long delta; ++ ++ /* sched_clock() is not guaranteed monotonic */ ++ if (now <= TASK_CPUSTATS(p).timestamp) { ++ TASK_CPUSTATS(p).timestamp = now; ++ return; ++ } ++ ++ delta = now - TASK_CPUSTATS(p).timestamp; ++ TASK_CPUSTATS(p).timestamp = now; ++ TASK_CPUSTATS(p).avg_delay_per_cycle += delta; ++ TASK_CPUSTATS(p).total_delay += delta; ++ RUNQ_CPUSTATS(p)->total_delay += delta; ++ if (task_is_sinbinned(p)) { ++ TASK_CPUSTATS(p).total_sinbin += delta; ++ RUNQ_CPUSTATS(p)->total_sinbin += delta; ++ } else if (rt_task(p)) { /* rt tasks are never sinbinned */ ++ RUNQ_CPUSTATS(p)->total_rt_delay += delta; ++ if (TASK_CPUSTATS(p).flags & CPUSTATS_WOKEN_FOR_INTR_FL) ++ RUNQ_CPUSTATS(p)->total_rt_intr_delay += delta; ++ } ++ if (unlikely(TASK_CPUSTATS(p).flags & CPUSTATS_JUST_FORKED_FL)) { ++ RUNQ_CPUSTATS(p)->total_fork_delay += delta; ++ TASK_CPUSTATS(p).flags &= ~CPUSTATS_JUST_FORKED_FL; ++ } ++ if (TASK_CPUSTATS(p).flags & CPUSTATS_WOKEN_FOR_INTR_FL) { ++ RUNQ_CPUSTATS(p)->total_intr_delay += delta; ++ TASK_CPUSTATS(p).flags &= ~CPUSTATS_WOKEN_FOR_INTR_FL; ++ } ++} ++ ++#define SCHED_AVG_ALPHA ((1 << SCHED_AVG_OFFSET) - 1) ++static inline void apply_sched_avg_decay(unsigned long long *valp) ++{ ++ *valp *= SCHED_AVG_ALPHA; ++ *valp >>= SCHED_AVG_OFFSET; ++} ++ ++static inline void decay_cpustats_for_cycle(struct task_struct *p) ++{ ++ apply_sched_avg_decay(&TASK_CPUSTATS(p).avg_sleep_per_cycle); ++ apply_sched_avg_decay(&TASK_CPUSTATS(p).avg_delay_per_cycle); ++ apply_sched_avg_decay(&TASK_CPUSTATS(p).avg_cpu_per_cycle); ++ TASK_CPUSTATS(p).avg_cycle_length = TASK_CPUSTATS(p).avg_sleep_per_cycle + ++ TASK_CPUSTATS(p).avg_delay_per_cycle + ++ TASK_CPUSTATS(p).avg_cpu_per_cycle; ++ /* take short cut and avoid possible divide by zero below */ ++ if (TASK_CPUSTATS(p).avg_cpu_per_cycle == 0) ++ TASK_CPUSTATS(p).cpu_usage_rate = 0; ++ else ++ TASK_CPUSTATS(p).cpu_usage_rate = calc_proportion(TASK_CPUSTATS(p).avg_cpu_per_cycle, TASK_CPUSTATS(p).avg_cycle_length); ++} ++ ++void update_cpustats_at_wake_up(struct task_struct *p, unsigned long long now) ++{ ++ delta_sleep_cpustats(p, now); ++ if (in_interrupt()) { ++ TASK_CPUSTATS(p).intr_wake_ups++; ++ TASK_CPUSTATS(p).flags |= CPUSTATS_WOKEN_FOR_INTR_FL; ++ } ++ TASK_CPUSTATS(p).total_wake_ups++; ++ decay_cpustats_for_cycle(p); ++} ++ ++void update_cpustats_at_end_of_ts(struct task_struct *p, unsigned long long now) ++{ ++ delta_cpu_cpustats(p, now); ++ decay_cpustats_for_cycle(p); ++} ++ ++int task_sched_cpustats(struct task_struct *p, char *buffer) ++{ ++ struct task_cpustats stats; ++ unsigned long nvcsw, nivcsw; /* context switch counts */ ++ int result; ++ ++ read_lock(&tasklist_lock); ++ result = get_task_cpustats(p, &stats); ++ nvcsw = p->nvcsw; ++ nivcsw = p-> nivcsw; ++ read_unlock(&tasklist_lock); ++ if (result) ++ return sprintf(buffer, "Data unavailable\n"); ++ return sprintf(buffer, ++ "%llu %llu %llu %llu %llu %llu %lu %lu @ %llu\n", ++ stats.total_sleep, ++ stats.total_cpu, ++ stats.total_delay, ++ stats.total_sinbin, ++ stats.total_wake_ups, ++ stats.intr_wake_ups, ++ nvcsw, nivcsw, ++ stats.timestamp); ++} ++ ++int cpustats_read_proc(char *page, char **start, off_t off, ++ int count, int *eof, void *data) ++{ ++ int i; ++ int len = 0; ++ int avail = 1; ++ struct cpu_cpustats total = {0, }; ++ ++ for_each_online_cpu(i) { ++ struct cpu_cpustats stats; ++ ++ if (get_cpu_cpustats(i, &stats) != 0) { ++ avail = 0; ++ break; ++ } ++ len += sprintf(page + len, ++ "cpu%02d %llu %llu %llu %llu %llu %llu %llu %llu @ %llu\n", i, ++ stats.total_idle, ++ stats.total_busy, ++ stats.total_delay, ++ stats.total_rt_delay, ++ stats.total_intr_delay, ++ stats.total_rt_intr_delay, ++ stats.total_sinbin, ++ stats.nr_switches, ++ stats.timestamp); ++ total.total_idle += stats.total_idle; ++ total.total_busy += stats.total_busy; ++ total.total_delay += stats.total_delay; ++ total.total_rt_delay += stats.total_rt_delay; ++ total.total_intr_delay += stats.total_intr_delay; ++ total.total_rt_intr_delay += stats.total_rt_intr_delay; ++ total.total_sinbin += stats.total_sinbin; ++ total.nr_switches += stats.nr_switches; ++ } ++ if (avail) ++ len += sprintf(page + len, "total %llu %llu %llu %llu %llu %llu %llu %llu\n", ++ total.total_idle, ++ total.total_busy, ++ total.total_delay, ++ total.total_intr_delay, ++ total.total_rt_delay, ++ total.total_rt_intr_delay, ++ total.total_sinbin, ++ total.nr_switches); ++ else ++ len = sprintf(page, "Data unavailable\n"); ++ ++ if (len <= off+count) *eof = 1; ++ *start = page + off; ++ len -= off; ++ if (len > count) len = count; ++ if (len < 0) len = 0; ++ ++ return len; ++} ++ ++static inline unsigned long long sched_div_64(unsigned long long a, unsigned long long b) ++{ ++#if BITS_PER_LONG < 64 ++ /* ++ * Assume that there's no 64 bit divide available ++ */ ++ if (a < b) ++ return 0; ++ /* ++ * Scale down until b less than 32 bits so that we can do ++ * a divide using do_div() ++ */ ++ while (b > ULONG_MAX) { a >>= 1; b >>= 1; } ++ ++ (void)do_div(a, (unsigned long)b); ++ ++ return a; ++#else ++ return a / b; ++#endif ++} ++ ++/* ++ * CPU usage rate is estimated as a proportion of a CPU using fixed denominator ++ * rational numbers. The denominator must be less than 2^24 so that ++ * we can store the eb_yardstick in an atomic_t on sparc ++ */ ++#if PROPORTION_OFFSET >= 24 ++#error "PROPORTION_OFFSET must be less than 24" ++#endif ++#define PROPORTION_OVERFLOW ((1ULL << (64 - PROPORTION_OFFSET)) - 1) ++ ++/* ++ * Convert a / b to a proportion in the range 0 to PROPORTION_ONE ++ * Requires a <= b or may get a divide by zero exception ++ */ ++unsigned long calc_proportion(unsigned long long a, unsigned long long b) ++{ ++ if (unlikely(a == b)) ++ return PROPORTION_ONE; ++ ++ while (a > PROPORTION_OVERFLOW) { a >>= 1; b >>= 1; } ++ ++ return sched_div_64(a << PROPORTION_OFFSET, b); ++} ++ ++/* ++ * Map the given proportion to an unsigned long in the specified range ++ * Requires range < PROPORTION_ONE to avoid overflow ++ */ ++unsigned long map_proportion(unsigned long prop, unsigned long range) ++{ ++ /* use 64 bits to help avoid overflow on 32 bit systems */ ++ return ((unsigned long long)prop * (unsigned long long)range) >> PROPORTION_OFFSET; ++} ++ ++/* WANT: proportion_to_ppt(ppt_to_proportion(x)) == x ++ */ ++unsigned long proportion_to_ppt(unsigned long proportion) ++{ ++ return ((unsigned long long)proportion * 2001ULL) >> (PROPORTION_OFFSET + 1); ++} ++ ++unsigned long ppt_to_proportion(unsigned long ppt) ++{ ++ return sched_div_64((unsigned long long)ppt * PROPORTION_ONE, 1000); ++} ++ ++unsigned long avg_cpu_usage_rate(const struct task_struct *p) ++{ ++ return TASK_CPUSTATS(p).cpu_usage_rate; ++} ++ ++unsigned long avg_sleep_rate(const struct task_struct *p) ++{ ++ /* take short cut and avoid possible divide by zero below */ ++ if (TASK_CPUSTATS(p).avg_sleep_per_cycle == 0) ++ return 0; ++ ++ return calc_proportion(TASK_CPUSTATS(p).avg_sleep_per_cycle, TASK_CPUSTATS(p).avg_cycle_length); ++} ++ ++unsigned long avg_cpu_delay_rate(const struct task_struct *p) ++{ ++ /* take short cut and avoid possible divide by zero below */ ++ if (TASK_CPUSTATS(p).avg_delay_per_cycle == 0) ++ return 0; ++ ++ return calc_proportion(TASK_CPUSTATS(p).avg_delay_per_cycle, TASK_CPUSTATS(p).avg_cycle_length); ++} ++ ++unsigned long delay_in_jiffies_for_usage(const struct task_struct *p, unsigned long rur) ++{ ++ unsigned long long acpc_jiffies, aspc_jiffies, res; ++ ++ if (rur == 0) ++ return ULONG_MAX; ++ ++ acpc_jiffies = sched_div_64(SCHED_AVG_RND(TASK_CPUSTATS(p).avg_cpu_per_cycle) * HZ, 1000000000); ++ aspc_jiffies = sched_div_64(SCHED_AVG_RND(TASK_CPUSTATS(p).avg_sleep_per_cycle) * HZ, 1000000000); ++ ++ /* ++ * we have to be careful about overflow and/or underflow ++ */ ++ while (unlikely(acpc_jiffies > PROPORTION_OVERFLOW)) { ++ acpc_jiffies >>= 1; ++ if (unlikely((rur >>= 1) == 0)) ++ return ULONG_MAX; ++ } ++ ++ res = sched_div_64(acpc_jiffies << PROPORTION_OFFSET, rur); ++ if (res > aspc_jiffies) ++ return res - aspc_jiffies; ++ else ++ return 0; ++} ++ ++static int convert_proportion(unsigned long *val, void *data, int write) ++{ ++ if (write) { ++ if (*val > 1000) ++ return -1; ++ *val = ppt_to_proportion(*val); ++ } else ++ *val = proportion_to_ppt(*val); ++ ++ return 0; ++} ++ ++int do_proc_proportion(ctl_table *ctp, int write, struct file *fp, ++ void __user *buffer, size_t *lenp, loff_t *ppos) ++{ ++ return do_proc_doulongvec_convf_minmax(ctp, write, fp, buffer, lenp, ++ ppos, convert_proportion, NULL); ++} +Index: 2.6.11/kernel/sched_zaphod.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ 2.6.11/kernel/sched_zaphod.c 2005-04-15 10:46:00.864566604 -0500 +@@ -0,0 +1,494 @@ ++/* ++ * kernel/sched_zaphod.c ++ * ++ * CPU scheduler mode ++ * ++ * Copyright (C) 2004 Aurema Pty Ltd ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#include ++#include ++ ++#include ++ ++#ifdef CONFIG_CPUSCHED_ZAPHOD ++#define MAX_PRIO ZAPHOD_MAX_PRIO ++#define MIN_NORMAL_PRIO ZAPHOD_MIN_NORMAL_PRIO ++#define IDLE_PRIO ZAPHOD_IDLE_PRIO ++#define BGND_PRIO ZAPHOD_BGND_PRIO ++#define TASK_ZD(p) (p)->u.zaphod.zaphod ++#define RUNQ_ZD(p) (p)->u.zaphod.zrq ++#define MIN_RATE_CAP(p) (p)->u.zaphod.min_cpu_rate_cap ++#define task_is_bgnd(p) (unlikely((p)->u.zaphod.cpu_rate_cap == 0)) ++#else ++#define TASK_CPUSTATS(p) (p)->cpustats ++#define TASK_ZD(p) (p)->zaphod ++#define RUNQ_ZD(p) (p)->zrq ++#define MIN_RATE_CAP(p) (p)->min_cpu_rate_cap ++#endif ++ ++#define EB_YARDSTICK_DECAY_INTERVAL 100 ++ ++enum zaphod_mode_enum { ++ ZAPHOD_MODE_PRIORITY_BASED, ++ ZAPHOD_MODE_ENTITLEMENT_BASED ++}; ++ ++static enum zaphod_mode_enum zaphod_mode = ZAPHOD_MODE_PRIORITY_BASED; ++ ++#ifdef CONFIG_SYSCTL ++static const char *zaphod_mode_names[] = { ++ "pb", /* ZAPHOD_MODE_PRIORITY_BASED */ ++ "eb", /* ZAPHOD_MODE_ENTITLEMENT_BASED */ ++ NULL /* end of list marker */ ++}; ++#endif ++ ++/* ++ * Convert nice to shares ++ * Proportional symmetry is aimed for: i.e. ++ * (nice_to_shares(0) / nice_to_shares(19)) == (nice_to_shares(-20) / nice_to_shares(0)) ++ * Make sure that this function is robust for variations of EB_SHARES_PER_NICE ++ */ ++static inline unsigned int nice_to_shares(int nice) ++{ ++ unsigned int result = DEFAULT_EB_SHARES; ++ ++ if (nice > 0) ++ result -= (nice * (20 * EB_SHARES_PER_NICE - 1)) / 19; ++ else if (nice < 0) ++ result += (nice * nice * ((20 * EB_SHARES_PER_NICE - 1) * EB_SHARES_PER_NICE)) / 20; ++ ++ return result; ++} ++ ++static inline int shares_to_nice(unsigned int shares) ++{ ++ int result = 0; ++ ++ if (shares > DEFAULT_EB_SHARES) ++ result = -int_sqrt((20 * (shares - DEFAULT_EB_SHARES)) / ++ (EB_SHARES_PER_NICE * (20 * EB_SHARES_PER_NICE - 1))); ++ else if (shares < DEFAULT_EB_SHARES) ++ result = (19 * (DEFAULT_EB_SHARES - shares)) / ++ (20 * EB_SHARES_PER_NICE - 1); ++ ++ return result; ++} ++ ++#define MAX_TOTAL_BONUS (BGND_PRIO - MAX_PRIO - 1) ++#define MAX_MAX_IA_BONUS ((MAX_TOTAL_BONUS + 1) / 2) ++#define MAX_MAX_TPT_BONUS (MAX_TOTAL_BONUS - MAX_MAX_IA_BONUS) ++#define DEFAULT_MAX_IA_BONUS ((MAX_MAX_IA_BONUS < 7) ? MAX_MAX_IA_BONUS : 7) ++#define DEFAULT_MAX_TPT_BONUS ((DEFAULT_MAX_IA_BONUS - 2) ? : 1) ++ ++ ++#define SCHED_IA_BONUS_OFFSET 8 ++#define SCHED_IA_BONUS_ALPHA ((1 << SCHED_IA_BONUS_OFFSET) - 1) ++#define SCHED_IA_BONUS_MUL(a, b) (((a) * (b)) >> SCHED_IA_BONUS_OFFSET) ++/* ++ * Get the rounded integer value of the interactive bonus ++ */ ++#define SCHED_IA_BONUS_RND(x) \ ++ (((x) + (1 << (SCHED_IA_BONUS_OFFSET - 1))) >> (SCHED_IA_BONUS_OFFSET)) ++ ++unsigned int max_ia_bonus = DEFAULT_MAX_IA_BONUS; ++unsigned int max_max_ia_bonus = MAX_MAX_IA_BONUS; ++unsigned int initial_ia_bonus = 1; ++unsigned int max_tpt_bonus = DEFAULT_MAX_TPT_BONUS; ++unsigned int max_max_tpt_bonus = MAX_MAX_TPT_BONUS; ++ ++/* ++ * Find the square root of a proportion ++ * Require: x <= PROPORTION_ONE ++ */ ++static unsigned long proportion_sqrt(unsigned long x) ++{ ++ /* use 64 bits internally to avoid overflow */ ++ unsigned long long res, b, ulx; ++ int bshift; ++ ++ /* ++ * Take shortcut AND prevent overflow ++ */ ++ if (x == PROPORTION_ONE) ++ return PROPORTION_ONE; ++ ++ res = 0; ++ b = (1UL << (PROPORTION_OFFSET - 1)); ++ bshift = PROPORTION_OFFSET - 1; ++ ulx = x << PROPORTION_OFFSET; ++ ++ for (; ulx && b; b >>= 1, bshift--) { ++ unsigned long long temp = (((res << 1) + b) << bshift); ++ ++ if (ulx >= temp) { ++ res += b; ++ ulx -= temp; ++ } ++ } ++ ++ return res; ++} ++ ++/* ++ * Tasks that have a CPU usage rate greater than this threshold (in parts per ++ * thousand) are considered to be CPU bound and start to lose interactive bonus ++ * points ++ */ ++#define DEFAULT_CPU_HOG_THRESHOLD 900 ++unsigned long cpu_hog_threshold = PROP_FM_PPT(DEFAULT_CPU_HOG_THRESHOLD); ++ ++/* ++ * Tasks that would sleep for more than 900 parts per thousand of the time if ++ * they had the CPU to themselves are considered to be interactive provided ++ * that their average sleep duration per scheduling cycle isn't too long ++ */ ++#define DEFAULT_IA_THRESHOLD 900 ++unsigned long ia_threshold = PROP_FM_PPT(DEFAULT_IA_THRESHOLD); ++#define LOWER_MAX_IA_SLEEP SCHED_AVG_REAL(15 * 60LL * NSEC_PER_SEC) ++#define UPPER_MAX_IA_SLEEP SCHED_AVG_REAL(2 * 60 * 60LL * NSEC_PER_SEC) ++ ++/* ++ * Calculate CPU usage rate and sleepiness. ++ * This never gets called on real time tasks ++ */ ++static unsigned long calc_sleepiness(task_t *p) ++{ ++ unsigned long long bl; ++ ++ bl = TASK_CPUSTATS(p).avg_sleep_per_cycle + TASK_CPUSTATS(p).avg_cpu_per_cycle; ++ /* ++ * Take a shortcut and avoid possible divide by zero ++ */ ++ if (unlikely(bl == 0)) ++ return PROPORTION_ONE; ++ else ++ return calc_proportion(TASK_CPUSTATS(p).avg_sleep_per_cycle, bl); ++} ++ ++static inline void decay_sched_ia_bonus(struct task_struct *p) ++{ ++ TASK_ZD(p).interactive_bonus *= SCHED_IA_BONUS_ALPHA; ++ TASK_ZD(p).interactive_bonus >>= SCHED_IA_BONUS_OFFSET; ++} ++ ++/* ++ * Check whether a task with an interactive bonus still qualifies and if not ++ * decrease its bonus ++ * This never gets called on real time tasks ++ */ ++static void reassess_cpu_boundness(task_t *p) ++{ ++ if (max_ia_bonus == 0) { ++ TASK_ZD(p).interactive_bonus = 0; ++ return; ++ } ++ /* ++ * No point going any further if there's no bonus to lose ++ */ ++ if (TASK_ZD(p).interactive_bonus == 0) ++ return; ++ ++ if (TASK_CPUSTATS(p).cpu_usage_rate > cpu_hog_threshold) ++ decay_sched_ia_bonus(p); ++} ++ ++/* ++ * Check whether a task qualifies for an interactive bonus and if it does ++ * increase its bonus ++ * This never gets called on real time tasks ++ */ ++static void reassess_interactiveness(task_t *p) ++{ ++ unsigned long sleepiness; ++ ++ if (max_ia_bonus == 0) { ++ TASK_ZD(p).interactive_bonus = 0; ++ return; ++ } ++ /* ++ * No sleep means not interactive (in most cases), but ++ */ ++ if (unlikely(TASK_CPUSTATS(p).avg_sleep_per_cycle > LOWER_MAX_IA_SLEEP)) { ++ /* ++ * Really long sleeps mean it's probably not interactive ++ */ ++ if (unlikely(TASK_CPUSTATS(p).avg_sleep_per_cycle > UPPER_MAX_IA_SLEEP)) ++ decay_sched_ia_bonus(p); ++ return; ++ } ++ ++ sleepiness = calc_sleepiness(p); ++ if (sleepiness > ia_threshold) { ++ decay_sched_ia_bonus(p); ++ TASK_ZD(p).interactive_bonus += map_proportion_rnd(sleepiness, max_ia_bonus); ++ } ++} ++ ++/* ++ * Check whether a task qualifies for a throughput bonus and if it does ++ * give it one ++ * This never gets called on real time tasks ++ */ ++#define NRUN_AVG_OFFSET 6 ++#define NRUN_AVG_ALPHA ((1 << NRUN_AVG_OFFSET) - 1) ++#define NRUN_AVG_ONE (1UL << NRUN_AVG_OFFSET) ++#define NRUN_AVG_MUL(a, b) (((a) * (b)) >> NRUN_AVG_OFFSET) ++static void recalc_throughput_bonus(task_t *p) ++{ ++ unsigned long long ratio; ++ unsigned long long expected_delay; ++ unsigned long long adjusted_delay; ++ unsigned long long load = RUNQ_ZD(p)->avg_nr_running; ++ ++ TASK_ZD(p).throughput_bonus = 0; ++ if (max_tpt_bonus == 0) ++ return; ++ ++ if (load <= NRUN_AVG_ONE) ++ expected_delay = 0; ++ else ++ expected_delay = NRUN_AVG_MUL(TASK_CPUSTATS(p).avg_cpu_per_cycle, (load - NRUN_AVG_ONE)); ++ ++ /* ++ * No unexpected delay means no bonus, but ++ * NB this test also avoids a possible divide by zero error if ++ * cpu is also zero and negative bonuses ++ */ ++ if (TASK_CPUSTATS(p).avg_delay_per_cycle <= expected_delay) ++ return; ++ ++ adjusted_delay = TASK_CPUSTATS(p).avg_delay_per_cycle - expected_delay; ++ ratio = calc_proportion(adjusted_delay, adjusted_delay + TASK_CPUSTATS(p).avg_cpu_per_cycle); ++ ratio = proportion_sqrt(ratio); ++ TASK_ZD(p).throughput_bonus = map_proportion_rnd(ratio, max_tpt_bonus); ++} ++ ++/* ++ * Calculate priority based priority (without bonuses). ++ * This never gets called on real time tasks ++ */ ++static void calculate_pb_pre_bonus_priority(task_t *p) ++{ ++ TASK_ZD(p).pre_bonus_priority = p->static_prio + MAX_TOTAL_BONUS; ++} ++ ++/* ++ * We're just trying to protect a reading and writing of the yardstick. ++ * We not to fussed about protecting the calculation so the following is ++ * adequate ++ */ ++static inline void decay_eb_yardstick(struct sched_zaphod_runq_data *zrq) ++{ ++ static const unsigned long decay_per_interval = PROP_FM_PPT(990); ++ unsigned long curry = atomic_read(&zrq->eb_yardstick); ++ unsigned long pny; /* potential new yardstick */ ++ struct task_struct *p = current; ++ ++ curry = map_proportion(decay_per_interval, curry); ++ atomic_set(&zrq->eb_ticks_to_decay, EB_YARDSTICK_DECAY_INTERVAL); ++ if (unlikely(rt_task(p) || task_is_bgnd(p))) ++ goto out; ++ if (TASK_CPUSTATS(p).cpu_usage_rate < MIN_RATE_CAP(p)) ++ pny = TASK_CPUSTATS(p).cpu_usage_rate / TASK_ZD(p).eb_shares; ++ else ++ pny = MIN_RATE_CAP(p) / TASK_ZD(p).eb_shares; ++ if (pny > curry) ++ curry = pny; ++out: ++ if (unlikely(curry >= PROPORTION_ONE)) ++ curry = PROPORTION_ONE - 1; ++ atomic_set(&zrq->eb_yardstick, curry); ++} ++ ++/* ++ * Calculate entitlement based priority (without bonuses). ++ * This never gets called on real time tasks ++ */ ++#define EB_PAR 19 ++static void calculate_eb_pre_bonus_priority(task_t *p) ++{ ++ /* ++ * Prevent possible divide by zero and take shortcut ++ */ ++ if (unlikely(MIN_RATE_CAP(p) == 0)) { ++ TASK_ZD(p).pre_bonus_priority = BGND_PRIO - 1; ++ } else if (TASK_CPUSTATS(p).cpu_usage_rate > MIN_RATE_CAP(p)) { ++ unsigned long cap_per_share = MIN_RATE_CAP(p) / TASK_ZD(p).eb_shares; ++ unsigned long prop = calc_proportion(MIN_RATE_CAP(p), TASK_CPUSTATS(p).cpu_usage_rate); ++ ++ TASK_ZD(p).pre_bonus_priority = (BGND_PRIO - 1); ++ TASK_ZD(p).pre_bonus_priority -= map_proportion_rnd(prop, EB_PAR + 1); ++ if (cap_per_share > atomic_read(&RUNQ_ZD(p)->eb_yardstick)) { ++ if (likely(cap_per_share < PROPORTION_ONE)) ++ atomic_set(&RUNQ_ZD(p)->eb_yardstick, cap_per_share); ++ else ++ atomic_set(&RUNQ_ZD(p)->eb_yardstick, PROPORTION_ONE - 1); ++ } ++ ++ } else { ++ unsigned long usage_per_share = TASK_CPUSTATS(p).cpu_usage_rate / TASK_ZD(p).eb_shares; ++ ++ if (usage_per_share > atomic_read(&RUNQ_ZD(p)->eb_yardstick)) { ++ if (likely(usage_per_share < PROPORTION_ONE)) ++ atomic_set(&RUNQ_ZD(p)->eb_yardstick, usage_per_share); ++ else ++ atomic_set(&RUNQ_ZD(p)->eb_yardstick, PROPORTION_ONE - 1); ++ TASK_ZD(p).pre_bonus_priority = MAX_RT_PRIO + MAX_TOTAL_BONUS + EB_PAR; ++ } else { ++ unsigned long prop; ++ ++ prop = calc_proportion(usage_per_share, atomic_read(&RUNQ_ZD(p)->eb_yardstick)); ++ TASK_ZD(p).pre_bonus_priority = MAX_RT_PRIO + MAX_TOTAL_BONUS; ++ TASK_ZD(p).pre_bonus_priority += map_proportion_rnd(prop, EB_PAR); ++ } ++ } ++} ++ ++static inline void calculate_pre_bonus_priority(task_t *p) ++{ ++ if (zaphod_mode == ZAPHOD_MODE_ENTITLEMENT_BASED) ++ calculate_eb_pre_bonus_priority(p); ++ else ++ calculate_pb_pre_bonus_priority(p); ++} ++ ++static DEFINE_PER_CPU(struct sched_zaphod_runq_data, zaphod_runqs); ++ ++void zaphod_init_cpu_runq_data(unsigned int cpu) ++{ ++ struct sched_zaphod_runq_data *zrq = &per_cpu(zaphod_runqs, cpu); ++ ++ zrq->avg_nr_running = 0; ++ atomic_set(&zrq->eb_yardstick, 0); ++ atomic_set(&zrq->eb_ticks_to_decay, EB_YARDSTICK_DECAY_INTERVAL + cpu); ++} ++ ++struct sched_zaphod_runq_data *zaphod_cpu_runq_data(unsigned int cpu) ++{ ++ return &per_cpu(zaphod_runqs, cpu); ++} ++ ++void zaphod_runq_data_tick(struct sched_zaphod_runq_data *zrq, unsigned long numr) ++{ ++ unsigned long nval = NRUN_AVG_MUL(zrq->avg_nr_running, NRUN_AVG_ALPHA); ++ nval += numr; ++ ++ zrq->avg_nr_running = nval; ++ ++ if (atomic_dec_and_test(&zrq->eb_ticks_to_decay)) ++ decay_eb_yardstick(zrq); ++} ++ ++void zaphod_fork(struct task_struct *p) ++{ ++ TASK_ZD(p).interactive_bonus = (max_ia_bonus >= initial_ia_bonus) ? ++ initial_ia_bonus : max_ia_bonus; ++ TASK_ZD(p).throughput_bonus = 0; ++} ++ ++unsigned int zaphod_effective_prio(struct task_struct *p) ++{ ++ unsigned int bonus = 0; ++ ++ /* no bonuses for tasks that have exceeded their cap */ ++ if (likely(TASK_CPUSTATS(p).cpu_usage_rate < MIN_RATE_CAP(p))) { ++ bonus = SCHED_IA_BONUS_RND(TASK_ZD(p).interactive_bonus); ++ bonus += TASK_ZD(p).throughput_bonus; ++ } ++ ++ return TASK_ZD(p).pre_bonus_priority - bonus; ++} ++ ++void zaphod_reassess_at_activation(struct task_struct *p) ++{ ++ recalc_throughput_bonus(p); ++ reassess_interactiveness(p); ++ calculate_pre_bonus_priority(p); ++} ++ ++void zaphod_reassess_at_end_of_ts(struct task_struct *p) ++{ ++ recalc_throughput_bonus(p); ++ reassess_cpu_boundness(p); ++ /* ++ * Arguably the interactive bonus should be updated here ++ * as well. But depends on whether we wish to encourage ++ * interactive tasks to maintain a high bonus or CPU bound ++ * tasks to lose some of there bonus? ++ */ ++ calculate_pre_bonus_priority(p); ++} ++ ++void zaphod_reassess_at_sinbin_release(struct task_struct *p) ++{ ++ calculate_pre_bonus_priority(p); ++} ++ ++void zaphod_reassess_at_renice(struct task_struct *p) ++{ ++ TASK_ZD(p).eb_shares = nice_to_shares(task_nice(p)); ++ if (!rt_task(p)) ++ calculate_pre_bonus_priority(p); ++} ++ ++#if defined(CONFIG_SYSCTL) ++static const unsigned int zero = 0; ++ ++#define ZAPHOD_MODE_BUFFER_LEN 16 ++char current_zaphod_mode[ZAPHOD_MODE_BUFFER_LEN] = ""; ++int proc_zaphod_mode(ctl_table *ctp, int write, struct file *fp, ++ void __user *buffer, size_t *lenp, loff_t *ppos) ++{ ++ int res; ++ ++ strcpy(current_zaphod_mode, zaphod_mode_names[zaphod_mode]); ++ res = proc_dostring(ctp, write, fp, buffer, lenp, ppos); ++ ++ if ((res == 0) && write) { ++ int i; ++ ++ for (i = 0; zaphod_mode_names[i] != NULL; i++) ++ if (strcmp(current_zaphod_mode, zaphod_mode_names[i]) == 0) ++ break; ++ if (zaphod_mode_names[i] == NULL) ++ res = -EINVAL; ++ else /* set the zaphod mode */ ++ zaphod_mode = i; ++ ++ strcpy(current_zaphod_mode, zaphod_mode_names[zaphod_mode]); ++ } ++ ++ return res; ++} ++ ++#ifndef CONFIG_CPUSCHED_ZAPHOD ++/* ++ * CPU scheduler control via /proc/sys/cpusched/xxx ++ */ ++enum ++{ ++ CPU_SCHED_ZAPHOD_END_OF_LIST=0, ++ ZAPHOD_SYSCTL_FNS() ++}; ++ ++struct ctl_table zaphod_ctl_table[] = { ++ ZAPHOD_CTL_TABLE_INIT(), ++ { .ctl_name = CPU_SCHED_ZAPHOD_END_OF_LIST } ++}; ++#endif ++#endif +Index: 2.6.11/kernel/sysctl.c +=================================================================== +--- 2.6.11.orig/kernel/sysctl.c 2005-04-14 19:29:15.619974684 -0500 ++++ 2.6.11/kernel/sysctl.c 2005-04-15 10:46:00.544473552 -0500 +@@ -143,6 +143,7 @@ + #ifdef CONFIG_UNIX98_PTYS + extern ctl_table pty_table[]; + #endif ++extern ctl_table cpu_sched_table[]; + + #ifdef HAVE_ARCH_PICK_MMAP_LAYOUT + int sysctl_legacy_va_layout; +@@ -215,6 +216,12 @@ + .mode = 0555, + .child = dev_table, + }, ++ { ++ .ctl_name = CTL_CPU_SCHED, ++ .procname = "cpu_sched", ++ .mode = 0555, ++ .child = cpu_sched_table, ++ }, + { .ctl_name = 0 } + }; + +@@ -1706,12 +1713,29 @@ + do_proc_dointvec_minmax_conv, ¶m); + } + +-static int do_proc_doulongvec_minmax(ctl_table *table, int write, ++/** ++ * Function pointer type: sysctl_ul_conf_t ++ * Interface for a function that changes the of (e.g. scale) an unsigned long value ++ * @table: a pointer to the unsigned long variable whose value is to be changed ++ * @write: %TRUE if this is a write to the sysctl file ++ * @data: a pointer to (optional) data required by the function. ++ * ++ * This function should change the value of the supplied variable depending ++ * on whether the data has been written to the file or is to be read form the ++ * file ++ * ++ * This routine MAY do range (or other) checking (e.g. overflow) when write is ++ * %TRUE if it wishes and signal that the supplied data should be rejected by ++ * returning an non zero value. ++ * ++ * Should return 0 on success. ++ */ ++int do_proc_doulongvec_convf_minmax(ctl_table *table, int write, + struct file *filp, + void __user *buffer, + size_t *lenp, loff_t *ppos, +- unsigned long convmul, +- unsigned long convdiv) ++ sysctl_ul_convf_t convf, ++ void *convdata) + { + #define TMPBUFLEN 21 + unsigned long *i, *min, *max, val; +@@ -1719,19 +1743,19 @@ + size_t len, left; + char buf[TMPBUFLEN], *p; + char __user *s = buffer; +- ++ + if (!table->data || !table->maxlen || !*lenp || + (*ppos && !write)) { + *lenp = 0; + return 0; + } +- ++ + i = (unsigned long *) table->data; + min = (unsigned long *) table->extra1; + max = (unsigned long *) table->extra2; + vleft = table->maxlen / sizeof(unsigned long); + left = *lenp; +- ++ + for (; left && vleft--; i++, min++, max++, first=0) { + if (write) { + while (left) { +@@ -1759,7 +1783,7 @@ + } + if (*p < '0' || *p > '9') + break; +- val = simple_strtoul(p, &p, 0) * convmul / convdiv ; ++ val = simple_strtoul(p, &p, 0); + len = p-buf; + if ((len < left) && *p && !isspace(*p)) + break; +@@ -1770,6 +1794,8 @@ + + if(neg) + continue; ++ if (convf && convf(&val, convdata, 1) != 0) ++ continue; + if ((min && val < *min) || (max && val > *max)) + continue; + *i = val; +@@ -1777,7 +1803,10 @@ + p = buf; + if (!first) + *p++ = '\t'; +- sprintf(p, "%lu", convdiv * (*i) / convmul); ++ val = *i; ++ if (convf) ++ (void)convf(&val, convdata, 0); ++ sprintf(p, "%lu", val); + len = strlen(buf); + if (len > left) + len = left; +@@ -1811,6 +1840,55 @@ + #undef TMPBUFLEN + } + ++struct ul_scale_data { ++ unsigned long convmul; ++ unsigned long convdiv; ++}; ++ ++/* Try to provide some protection against overflow including intermediate ++ * overflow where possible (i.e. on 32 bit systems) ++ */ ++static int ul_scale(unsigned long *val, void *data, int write) ++{ ++ struct ul_scale_data *sdp = (struct ul_scale_data *)data; ++ unsigned long long tl; ++ ++ if (write) { ++ tl = (*val) * sdp->convmul; ++ (void)do_div(tl, sdp->convdiv); ++ } else { ++ unsigned long rem; ++ ++ tl = (*val) * sdp->convdiv; ++ rem = do_div(tl, sdp->convmul); ++ if (rem > (sdp->convmul >> 1)) ++ tl++; ++ } ++ ++ if (tl > ULONG_MAX) ++ return -1; ++ ++ *val = tl; ++ ++ return 0; ++} ++ ++static int do_proc_doulongvec_minmax(ctl_table *table, int write, ++ struct file *filp, ++ void __user *buffer, ++ size_t *lenp, loff_t *ppos, ++ unsigned long convmul, ++ unsigned long convdiv) ++{ ++ struct ul_scale_data sd; ++ ++ sd.convmul = convmul; ++ sd.convdiv = convdiv; ++ ++ return do_proc_doulongvec_convf_minmax(table, write, filp, buffer, lenp, ++ ppos, ul_scale, &sd); ++} ++ + /** + * proc_doulongvec_minmax - read a vector of long integers with min/max values + * @table: the sysctl table +@@ -2053,6 +2131,15 @@ + return -ENOSYS; + } + ++int do_proc_doulongvec_convf_minmax(ctl_table *table, int write, ++ struct file *filp, ++ void __user *buffer, ++ size_t *lenp, loff_t *ppos, ++ sysctl_ul_convf_t convf, ++ void *convdata) ++{ ++ return -ENOSYS; ++} + + #endif /* CONFIG_PROC_FS */ + +@@ -2288,6 +2375,16 @@ + return -ENOSYS; + } + ++int do_proc_doulongvec_convf_minmax(ctl_table *table, int write, ++ struct file *filp, ++ void __user *buffer, ++ size_t *lenp, loff_t *ppos, ++ sysctl_ul_convf_t convf, ++ void *convdata) ++{ ++ return -ENOSYS; ++} ++ + struct ctl_table_header * register_sysctl_table(ctl_table * table, + int insert_at_head) + { +@@ -2310,6 +2407,7 @@ + EXPORT_SYMBOL(proc_dointvec_userhz_jiffies); + EXPORT_SYMBOL(proc_dointvec_ms_jiffies); + EXPORT_SYMBOL(proc_dostring); ++EXPORT_SYMBOL(do_proc_doulongvec_convf_minmax); + EXPORT_SYMBOL(proc_doulongvec_minmax); + EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax); + EXPORT_SYMBOL(register_sysctl_table);