ImageDecoderFramework Examples
ImageDecoderFramework.js is a Javascript library for heavy decoding of images which are decoded by custom logic. It was designed especially to show the images in a web viewer like Cesium or Leaflet, besides an API that supports image decoding for wide applicative needs.
The main advantages of using the library over implementing your image directly on top of one of the popular viewers API (e.g. Cesium's ImageryProvider or Leaflet's layers) are:
- Heavy use of Web Workers, which allow better interactivity.
- Support progressive fetch of gradually improved quality.
- An intermediate level between image implementation and viewer: Once an image is implemented, it may be used easily in both Leaflet and Cesium. Moreover, once implemented a plugin for your favorite viewer you may use it for any image.
Once an image is implemented, the API of using it (for example to show part of it in HTML page or put it on a viewer) is relatively simple. However implementing the underlying image requires training on the API. In addition, the spatial calculations of the exact data to be fetched and pixels to be drawn on decode may be unintuitive without some experience with viewer infrastructure implementations.
Using the library requires the following script imports:
<script src="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js"></script>
<script src="Cesium-1.20/Cesium.js"></script><!-- downloaded locally -->
<script src="http://MaMazav.github.io/cdn/image-decoder-framework.dev.js"></script>
Image Implementation Overview
An image requires implementing a top-level Image class for all internal implementation. The image should hold three other classes that together implement the image functionality:
- Fetcher - fetches the image parameters and the image data from server.
- InputRetriever implementation for Dependency Workers - manages the Web Workers that perform the actual decoding. It should be implemented by the depdendency-workers.js library API. If using gridimagebase some of the dependency-workers.js requirements are already fulfilled.
- LevelCalculator - provides conversion between screen resolution and level index, for multiple resolution images.
Whereas manually implementing all the functionality of those classes gives a lot of power, it may be too complicated for simple images. The GridImageBase and FetcherBase classes that are explained below are recommended for simple image implementation.
Notice that each object of these classes may live in another Web Worker. Thus all method arguments, method results and even exceptions should be serializable. You don't need to treat the serialization and manage the Web Workers, just make sure that all data supports structured clones.
Let's look on a simple example. This example shows an image that contains some resolution levels. Each resolution level is splitted into rectangular tiles (as in a standard "pyramid" - a common technique in the area of graphic viewers). The image is blue except of the tile borders which are cyan.
GridFetcherBase
First we need to implement the Fetcher. Inheriting the GridFetcherBase is an easy way to create a fetcher that fits our purpose. It requires implementing of three methods: open, fetchTile and getImageParams. The open method is called once and should return a promise that successfully terminates when the image is ready. The fetchTile performs the actual fetch of a single tile within a specific resolution level. The getImageParams should return an object contains the parameters of the image. The image parameters object should be returned also in the open method Promise result.
The image parameters should contain at least the following fields:
- imageLevel - a reference resolution level of the image. The reference level is used only for consistency of calculations (sizes returned by various methods of the image should be in terms of the reference level) and doesn't have any applicative meaning for viewers. To simplify calculation it's usually better to choose the best resolution level as a reference level.
- imageWidth, imageHeight - the size of the image, in terms of the imageLevel.
- numResolutionLevelsForLimittedViewer - count of resolution levels. Even if the image is dynamic and may adapt to any resolution, some viewers may not have the ability for that and you'll have to choose some limitation for the resolution level count.
- lowestQuality, highestQuality - An advanced feature that may be used to define progressive quality within a given resolution level (e.g. as in Jpeg2000's quality layers). A lot of image implementations doesn't need it, and may put here an arbitrary value.
- tileWidth, tileHeight - Single tile size, Required only for images that inherit GridFetcher and GridImage.
Besides those arguments, additional arguments may be added to the image parameters object. The image parameters object is later passed to the image by the opened method (see below). Besides being a consistent way to pass this parameters, it also provides a way to pass this argument across Web Workers if the Fetcher and Image are not on same Web Worker.
GridImageBase
Now that we have a Fetcher implemented, we need the Image and DependencyWorkers classes. Fortunately the GridImageBase implements most of their functionality given that our image is a conventional grid-structured. We only need to implement two methods: The opened method which is called after the Fetcher.opened terminated successfully (don't forget to call the base's opened method!), and the getDecodeWorkerTypeOptions which returns the data required to initialize a Web Worker that decode a single tile (same Web Worker data required for the Web Workers in depdendency-workers.js library).
Notice that we also overrode the getLevelCalcualtor. This method can optionally be overriden to change the default LevelCalculator behavior provided by the GridImage. The default implementation represents an image with infinite resolution levels, where each level is four times bigger than the previous level (two times for each axis). In that example we override the default behavior of the GridImage to show how we create a finite-resolution image. You also may choose to implement an absolutely different LevelsCalculator (see the default GridLevelCalculator implementation as an example).
Decoder Worker: Web Worker for actual decode
Finally we need the Web Worker implementation which actually decode a single tile:
That's all! We have the implemented image. Now let's see how can you easily convert this code into a graphic view using Leaflet.
Showing image in Leaflet
Using the following several lines, your image will be shown in leaflet:
Notice that you the workersLimit argument is optional and has a default value of 5. This argument limits the count of Web Workers used for decoding (excluding the fetch Web Worker). We limitted it in this demo because this page contains four images, and too many Web Workers causes instability issues in mobile device browsers.
Now that we've seen the whole picture of the simplest use of the image-decoder-framework.js library, we would like to extend our knowledge about additional features that the library allows.
Another image: Sierpinski carpet
The following example is more complex example of an image which represents Sierpinski carpet image. It uses a graphics library which luckily supports by-region partial calculation of the Sierpinski squares coordinates (well, actually this "library" was written especially for this demo page...).
The Sierpinski carpet image does not demonstrate a new feature of the framework. It is just another more complex reference example of the framework. In addition we will improve this example to demonstrate progressiveness later (please ignore the getLowestQuality and getHighestQuality methods now - as mentioned above, they are not effective without progressiveness support).
Leaflet Sierpinski ImageDecoder Demo
Top level image implementation of Sierpinski carpet:
Sierpinski carpet image fetcher implementation:
Sierpinski decoder worker implementation:
Progressive fetch
Assume you have a heavy image, which is hard to be loaded or decoded. However this image may be splitted into lower qualities, which allows showing a quick lower quality image until the better image will be shown. In this case you may find progressiveness a very useful feature. Unfortunately not all viewers support it easily.
Imagine that calculating Sierpinski square positions is a very heavy task. (later 'll demonstrate it by adding 500ms delay). As we show squares of smaller size, the count of the square increases and the quality improves. Luckily again, the graphics library enable bounding the square size to lower value to improve performance over quality. Let's reimplement our fetcher to support progressive calculation of Sierpinski squares (the progressive version of Sierpinski carpet image inherits the simple one and overrides only the required changes for progressiveness):
Leaflet Progressive ImageDecoder Demo
The top level image implementation of Sierpinski carpet is slightly changed:
The fetcher implementation, however, is more sensitive to progressiveness:
The quality does not affect the decoder worker which only takes a list of squares as an input (although there may be cases in which the worker implementation should be changed to support progressiveness).
Showing image in Cesium
The natural way to implement an image in Cesium is to implement an ImageryProvider. This API has a lot of advantages like natural integration into Cesium, tile caching, etc. However this API does not support progressiveness. We provide the two alternatives: CesiumImageDecoderLayerManager is an implementation which support progressiveness, and ImageDecoderImageryProvider which is more stable and enjoys other Cesium's ImageryProvider advantages if you don't care about progressiveness:
CesiumImageDecoderLayerManager
CesiumImageDecoderLayerManager Demo
(In new Cesium versions we have a serious blinking issue, hope to solve it soon).
The code behind showing an image in Cesium (given that the image is already implemented as above):
ImageDecoderImageryProvider
The API of ImageDecoderImageryProvide is more similar to the standard Cesium API than the CesiumImageDecoderLayerManager demonstrated above. However, one point which is counter-intuitive is the fact that ImageDecoderImageryProvider requires its parent viewer or widget as the constructor parameter. The reason is performance: Cesium tends to request a lot of tiles, especially when the user moves quickly but also for prefetch reasons. It may significantly degrade performance in the context of heavy decoding images. Thus the framework uses scheduling mechanism to prioritize and even abort some requests. The framework uses the information about the current view area for this prioritization, thus it needs the viewer.
ImageDecoderImageryProvider Demo
Render image to canvas
To render an image to canvas, ImageDecoder.renderToCanvas may be used. The region from the image and region in the canvas can be set by the passed arguments. Once started, the renderToCanvas function takes control over the canvas and render the pixels to it. Click on the button below the code to activate the demo:
Programmatically get pixels of region in image
Until now we saw only high level interfaces for using the image with Leaflet and Cesium viewers. One can also use the ImageDecoder class to get the pixels programmatically and do it whatever he would like. The following example demonstrate how to decode a region of interest from the image and use it within a simple canvas - i.e. achieve almost same behavior as in previous demo, but manually (click on the button below the code to activate the demo):
Showing image in arbitrary viewer
Besides the ImageDecoder demonstrated above, there is also API which is more optimized for viewers. The class ViewerImageDecoder will manage a canvas for you, including caching already-rendered regions, canvas resizing, and always rendering low-resolution image in the back to avoid empty areas blinkin. You only need to let the ViewerImageDecoder know when and where the viewer moves, and update the canvas position according to the ViewerImageDecoder callbacks.
The example below shows how to use the image with a super simple viewer implemented in the graphics library (same graphics library mentioned above which was written for this demo).


Home
Be Aware of Your...
Motivations
adventurous
quirky
challenging
always wanted to
expand horizons
told I could not
Possible Issues
physically demanding
very costly
temporal concerns
passport current
vaccinations current
could be fatal
Biography
<EMAIL_ADDRESS>Submit >


Nosedive explores beyond the current limits of games of maneuver. Rather than moving pieces, players explore an island by drawing directly on the board, creating aesthetic works through play. Every match ends with a permanent record of the game, which can be evaluated both tactically and as a visual artifact. Nosedive is for tactical game veterans and beginners alike. We invite you to try this unique approach to a classic style of play.
Nosedive 试图探索桌面游戏游戏移动的边界。玩家并不简单地移动部件，而是真正在版面上构图绘画，在游玩的过程中创造出飞行的归结。每一场战斗结束后，都可以通过战略和美感的角度对游戏进行评价。Nosedive不仅是给硬核桌游玩家创造的，而且也支持初学者的游玩。
Nosedive has been positively received by playtesters, those new to the tactical maneuver genre, experienced wargamers, and industry veterans. I’m especially proud to say that Nosedive was an IndieCade 2016 Table Games Selection.
Nosedive 被测试者们广泛接受，无论是经验丰富的设计师、老派战棋游戏玩家，还是新的策略游戏玩家。Nosedive亦入围2016年 IndieCade Selection （桌游组）。
Videos can be watched here.
视频可以在这里查看。


HOLCF: A higher-order version of LCF based on Isabelle/HOL
HOLCF is the definitional extension of Church's Higher-Order Logic with
Scott's Logic for Computable Functions that has been implemented in the
theorem prover Isabelle. This results in a flexible setup for reasoning
about functional programs. HOLCF supports standard domain theory (in particular
fixpoint reasoning and recursive domain equations) but also coinductive
arguments about lazy datatypes.
The most recent description of HOLCF is found here:
Descriptions of earlier versions can also be found online:
A detailed description (in German) of the entire development can be found in:
A short survey is available in:


01 Apr 2020 Marta Paes (@morsapaes)
While things slow down around us, the Apache Flink community is privileged to remain as active as ever. This blogpost combs through the past few months to give you an update on the state of things in Flink — from core releases to Stateful Functions; from some good old community stats to a new development blog.
And since now it’s more important than ever to keep up the spirits, we’d like to invite you to join the Flink Forward Virtual Conference, on April 22-24 (see Upcoming Events). Hope to see you there!
The Year (so far) in Flink
Flink 1.10 Release
To kick off the new year, the Flink community released Flink 1.10 with the record contribution of over 200 engineers. This release introduced significant improvements to the overall performance and stability of Flink jobs, a preview of native Kubernetes integration and advances in Python support (PyFlink). Flink 1.10 also marked the completion of the Blink integration, hardening streaming SQL and bringing mature batch processing to Flink with production-ready Hive integration and TPC-DS coverage.
The community is now discussing the release of Flink 1.10.1, covering some outstanding bugs from Flink 1.10.
Stateful Functions Contribution and 2.0 Release
Last January, the first version of Stateful Functions (statefun.io) code was pushed to the Flink repository. Stateful Functions started out as an API to build general purpose event-driven applications on Flink, taking advantage of its advanced state management mechanism to cut the “middleman” that usually handles state coordination in such applications (e.g. a database).
In a recent update, some new features were announced, like multi-language support (including a Python SDK), function unit testing and Stateful Functions’ own flavor of the State Processor API. The release cycle will be independent from core Flink releases and the Release Candidate (RC) has been created — so, you can expect Stateful Functions 2.0 to be released very soon!
Building up to Flink 1.11
Amidst the usual outpour of discussion threads, JIRA tickets and FLIPs, the community is working full steam on bringing Flink 1.11 to life in the next few months. The feature freeze is currently scheduled for late April, so the release is expected around mid May. The upcoming release will focus on new features and integrations that broaden the scope of Flink use cases, as well as core runtime enhancements to streamline the operations of complex deployments.
Some of the plans on the use case side include support for changelog streams in the Table API/SQL (FLIP-105), easy streaming data ingestion into Apache Hive (FLIP-115) and support for Pandas DataFrames in PyFlink. On the operational side, the much anticipated new Source API (FLIP-27) will unify batch and streaming sources, and improve out-of-the-box event-time behavior; while unaligned checkpoints (FLIP-76) and some changes to network memory management will allow to speed up checkpointing under backpressure.
Throw into the mix improvements around type systems, the WebUI, metrics reporting and supported formats, this release is bound to keep the community busy. For a complete overview of the ongoing development, check this discussion and follow the weekly updates on the Flink @community mailing list.
New Committers and PMC Members
The Apache Flink community has welcomed 1 PMC (Project Management Committee) Member and 5 new Committers since the last update (September 2019):
New PMC Members
Jark Wu
New Committers
Zili Chen, Jingsong Lee, Yu Li, Dian Fu, Zhu Zhu
Congratulations to all and thank you for your hardworking commitment to Flink!
The Bigger Picture
A Look into the Flink Repository
In the last update, we shared some numbers around Flink releases and mailing list activity. This time, we’re looking into the activity in the Flink repository and how it’s evolving.
There is a clear upward trend in the number of contributions to the repository, based on the number of commits. This reflects the fast pace of development the project is experiencing and also the successful integration of the China-based Flink contributors started early last year. To complement these observations, the repository registered a 1.5x increase in the number of individual contributors in 2019, compared to the previous year.
But did this increase in capacity produce any other measurable benefits?
If we look at the average time of Pull Request (PR) “resolution”, it seems like it did: the average time it takes to close a PR these days has been steadily decreasing since last year, sitting between 5-6 days for the past few months.
These are great indicators of the health of Flink as an open source project!
Flink Community Packages
If you missed the launch of flink-packages.org, here’s a reminder! Ververica has created (and open sourced) a website that showcases the work of the community to push forward the ecosystem surrounding Flink. There, you can explore existing packages (like the Pravega and Pulsar Flink connectors, or the Flink Kubernetes operators developed by Google and Lyft) and also submit your own contributions to the ecosystem.
Flink “Engine Room”
The community has recently launched the “Engine Room”, a dedicated space in Flink’s Wiki for knowledge sharing between contributors. The goal of this initiative is to make ongoing development on Flink internals more transparent across different work streams, and also to help new contributors get on board with best practices. The first blogpost is already up and sheds light on the migration of Flink’s CI infrastructure from Travis to Azure Pipelines.
Upcoming Events
Flink Forward Virtual Conference
The organization of Flink Forward had to make the hard decision of cancelling this year’s event in San Francisco. But all is not lost! Flink Forward SF will be held online on April 22-24 and you can register (for free) here. Join the community for interactive talks and Q&A sessions with core Flink contributors and companies like Splunk, Lyft, Netflix or Google.
Others
Events across the globe have come to a halt due to the growing concerns around COVID-19, so this time we’ll leave you with some interesting content to read instead. In addition to this written content, you can also recap last year’s sessions from Flink Forward Berlin and Flink Forward China!
If you’d like to keep a closer eye on what’s happening in the community, subscribe to the Flink @community mailing list to get fine-grained weekly updates, upcoming event announcements and more.


| [t]Your e-mail to the consultant responsible for this candidate or vacancy was sent succesfully. You can now continue using our Vendor Management Portal. Thank you for your response. The application will now automatically take you back to the previous page. [/t] |


Returns one or more snapshot objects, which contain metadata about your cluster snapshots. By default, this operation returns information about all snapshots of all clusters that are owned by you AWS customer account. No information is returned for snapshots owned by inactive AWS customer accounts.
describe-cluster-snapshots
[--cluster-identifier <value>]
[--snapshot-identifier <value>]
[--snapshot-type <value>]
[--start-time <value>]
[--end-time <value>]
[--max-records <value>]
[--marker <value>]
[--owner-account <value>]
The identifier of the cluster for which information about snapshots is requested.
--snapshot-identifier (string)
The snapshot identifier of the snapshot about which to return information.
The type of snapshots for which you are requesting information. By default, snapshots of all types are returned.
Valid Values: automated | manual
A value that requests only snapshots created at or after the specified time. The time value is specified in ISO 8601 format. For more information about ISO 8601, go to the ISO8601 Wikipedia page.
Example: 2012-07-16T18:00:00Z
A time value that requests only snapshots created at or before the specified time. The time value is specified in ISO 8601 format. For more information about ISO 8601, go to the ISO8601 Wikipedia page.
Example: 2012-07-16T18:00:00Z
The maximum number of snapshot records to include in the response. If more records exist than the specified --max-records value, the response returns a marker that you can use in a subsequent describe-cluster-snapshots request in order to retrieve the next set of snapshot records.
Default: 100
Constraints: Must be at least 20 and no more than 100.
An optional marker returned by a previous describe-cluster-snapshots request to indicate the first snapshot that the request will return.
The AWS customer account used to create or copy the snapshot. Use this field to filter the results to snapshots owned by a particular account. To describe snapshots you own, either specify your AWS customer account, or do not specify the parameter.
This example returns a description of all cluster snapshots for the account. By default, the output is in JSON format.
Command:
aws redshift describe-cluster-snapshots
Result:
{
"Snapshots": [
{
"Status": "available",
"SnapshotCreateTime": "2013-07-17T22:02:22.852Z",
"EstimatedSecondsToCompletion": -1,
"AvailabilityZone": "us-east-1a",
"ClusterVersion": "1.0",
"MasterUsername": "adminuser",
"Encrypted": false,
"OwnerAccount": "111122223333",
"BackupProgressInMegabytes": 20.0,
"ElapsedTimeInSeconds": 0,
"DBName": "dev",
"CurrentBackupRateInMegabytesPerSecond: 0.0,
"ClusterCreateTime": "2013-01-22T21:59:29.559Z",
"ActualIncrementalBackupSizeInMegabytes"; 20.0
"SnapshotType": "automated",
"NodeType": "dw.hs1.xlarge",
"ClusterIdentifier": "mycluster",
"Port": 5439,
"TotalBackupSizeInMegabytes": 20.0,
"NumberOfNodes": "2",
"SnapshotIdentifier": "cm:mycluster-2013-01-22-22-04-18"
},
{
"EstimatedSecondsToCompletion": 0,
"OwnerAccount": "111122223333",
"CurrentBackupRateInMegabytesPerSecond: 0.1534,
"ActualIncrementalBackupSizeInMegabytes"; 11.0,
"NumberOfNodes": "2",
"Status": "available",
"ClusterVersion": "1.0",
"MasterUsername": "adminuser",
"AccountsWithRestoreAccess": [
{
"AccountID": "444455556666"
} ],
"TotalBackupSizeInMegabytes": 20.0,
"DBName": "dev",
"BackupProgressInMegabytes": 11.0,
"ClusterCreateTime": "2013-01-22T21:59:29.559Z",
"ElapsedTimeInSeconds": 0,
"ClusterIdentifier": "mycluster",
"SnapshotCreateTime": "2013-07-17T22:04:18.947Z",
"AvailabilityZone": "us-east-1a",
"NodeType": "dw.hs1.xlarge",
"Encrypted": false,
"SnapshotType": "manual",
"Port": 5439,
"SnapshotIdentifier": "my-snapshot-id"
} ]
}
(...remaining output omitted...)


{% extends "global/Base.html" %} {% load staticfiles otree_tags %} {% block title %} Instructions {% endblock %} {% block content %}
WELCOME!
Please read the following instructions carefully.
This is an experiment in decision-making. The amount of money you earn will depend upon the decisions you make, and on the decisions other participants make. Your earnings are given in tokens. This experiment has three parts. Your total earnings will be the sum of your payoffs in each part. At the end of the experiment you will be paid IN CASH based on the following exchange rate:
£1 = 250 tokens
In addition, you will be paid £5 for participation. Everyone will be paid in private and you are under no obligation to tell others how much you have earned.
Please do not talk or communicate with other participants during the experiment or look at other participants' computer screens. Please turn off your mobile phones to avoid any distractions. If you have a question, feel free to raise your hand, and an experimenter will come to help you.
{% endblock %}


The Grand Tour Trio Trade Wheels For Hulls In 'Seamen' Trailer
The double entendre is strong with this one.
by Christopher SmithWhen The Grand Tour’s third season came to a close, it was a legitimately sad moment. The motoring trio of Richard Hammond, James May, and Jeremy Clarkson bid farewell to the studio audience format that made them world-famous over the course of nearly 20 years, notably with BBC’s Top Gear. At the conclusion of that episode, the three wise men gentlemen blokes pledged to keep going with adventures. The first of those adventures is almost here, and the new video trailer for it looks pretty darned good.
Grand Touring:
As the trailer clearly explains at the very beginning, The Grand Tour team will attempt to cross Vietnam’s Mekong Delta. Sounds simple in theory, but lest we forget – we’re dealing with Clarkson, Hammond, and May here. Not only that, this time around the trio won’t be motoring about in cars, but boats. Hence the title of the special being The Grand Tour Presents: Seamen. We probably don’t need to explain the double entendre there, but for those confused, well, we're still not going to explain it. And trust us when we say you don’t want to Google it.
Gallery: The Grand Tour Seaman Special
What can we expect from this adventure? At nearly two minutes long, this trailer shows the men bickering, getting hit with water, getting hit by each other, and hitting most every object around them. At some point they get lost, then lose their GPS system. And the boats almost certainly won’t arrive at their destinations looking the same as when they left. You know, standard Clarkson-Hammond-May tomfoolery.
Admittedly, we’ve missed seeing these guys on the television so this trailer is welcomed with open arms. And we don’t have long to wait for the full program, as it’s slated for a December 13 launch on Amazon Prime, which happens to be a Friday. Is that a coincidental choice, or foreboding foreshadowing of what’s to come?
Probably a bit of both, actually.
Source: The Grand Tour via YouTube


NOTE: The MCP 2.1 Specification has moved to http://www.moo.mud.org/mcp/. This copy is maintained for archival purposes only and may be removed or out-of-date.
See also the mailing list archive, the MCP 1.0 spec at JHM, and Dave's powerpoint slides from a talk on MCP (or the HTML version of those slides) for background information about this specification.
Advances in MUD server design, particularly the development of in-server programming languages, coupled with the replacement of terminals and telnet sessions by personal computers and customized (and frequently user-programmable) clients have given rise to a demand for MUD-based applications which make use of modern client capabilities such as windowing systems, local file storage, and richer text display. At the same time, many MUD servers have retained the model of a single 7-bit ASCII channel per client, constraining the application author's ability to design protocols.
The MUD Client Protocol (MCP) defines a simple and standard message format for the protocols used in constructing these applications. It is designed to be readily distinguished from the normal stream of MUD output and user commands and easily parsed.
MCP is an attempt to provide a standard message format on which to build MUD-based client-server applications. As described above, many MUDs place restrictions on the user's I/O channel. Given these, a survey of MCP's goals is in order:
Much of MCP is described in terms which require some understanding of the typical MUD architecture (that is, a central server reflecting messages among, and generating messages to, multiple clients). For the reader who is unfamiliar with MUDs, the terms used may be somewhat unclear. This section attempts to document some of the terms used in this specification.
This document describes version 2.1 of MCP; version 1.0 is described in the form of online help at JHM (telnet://jhm.ccs.neu.edu:1709), and written by Erik Ostrom, Dave Van Buren, Pavel Curtis, David Nichols, and Jay Carlson. A number of implementations revised and extended this specification, and some of those implementations advertised themselves as version 2.0. This specification includes features from some of those existing systems. Because, however, there are significant departures from these implementations, it was decided to number this specification 2.1 to avoid conflicts.
MCP 2.1 consists of a number of cooperating parts. Some of the parts specified here are required for any compliant MCP 2.1 implementation. Others are optional; however, implementations are strongly encouraged to implement the optional parts of MCP 2.1. Experience has shown that these optional components are extremely useful. The components covered by this specification and their status (required or optional) are:
Implementations which choose not to implement the optional parts of this specification must not provide features which conflict with the optional parts. In particular, implementations which choose not to implement cords or multiline messages are forbidden from using the following messages in other packages: #$#*, #$#:, #$#mcp-cord-open, #$#mcp-cord, and #$#mcp-cord-closed. Implementations which do not implement multilines should treat a parameter with an asterisk at the end of its name as an error.
MCP is intended to solve the problem of identifying and routing out-of-band information in a single network stream. This suggests a model for implementations to follow consisting of three active components and four data flows, reflected on either end of the network stream. A graphic view of this model is shown here:
Network lines are transmitted between network translation layers, which identify the lines as either in-band lines (which, modulo quoting, are exchanged directly between the MUD client and server and the network), or out-of-band lines. Out-of-band lines are handled by an MCP parser, which turns them into messages to be handled by the client or server.
This specification is primarily concerned with the details of messages entering and leaving the MCP parser. The job of the network line translation layer will be dealt with briefly, followed by the details of parsing an MCP message. Finally, the specification presents the details of version negotiation and presents a typical MCP package, a protocol built on MCP.
MCP implementations require a translation layer between their message-handling system (which processes out-of-band message lines) and the network to which the system is attached. The job of this translation layer is to translate network lines into in-band lines and out-of-band lines, and route these lines appropriately.
When receiving a network line, the translation layer should apply the following rules:
#$"#$#this isn't: really an: "out-of-band message"must be translated to:
#$#this isn't: really an: "out-of-band message"and treated as an in-band line by the implementing MUD or client.
When sending lines to the network, the translation layer should apply the following rules:
<message> ::= <message-start> | <message-continue> | <message-end> <message-start> ::= <message-name> <space> <auth-key> <keyvals>
An MCP message consists of three parts: the name of the message, the authentication key, and a set of keywords and their associated values. The message name indicates what action is to be performed; if the given message name is unknown, the message should be ignored. The authentication key is generated at the beginning of the session; if it is incorrect, the message should be ignored. The keyword-value pairs specify the arguments to the message. These arguments may occur in any order, and the ordering of the arguments does not affect the semantics of the message. There is no limit on the number of keyword-value pairs which may appear in a message, or on the lengths of message names, keywords, or values.
<keyvals> ::= '' | <space> <keyval> <keyvals> <keyval> ::= <key> ':' <space> <value> <key> ::= <simple-key> | <multiline-key> <simple-key> ::= <ident> <multiline-key> ::= <ident> '*'
Each argument to a message is named by a keyword. The keyword consists of an identifier (a string matching the <ident> nonterminal), optionally followed by an asterisk; if the asterisk is present, the value to follow is a multiline value. If no asterisk is present, the value is simple. Messages may contain a mixture of simple and multiline values.
Implementations should never send a simple message with duplicate argument keywords on the same line; for example, the message
#$#say 12345 what: "Hi there!" WHAT: "Hey there..." from: Biff to: Betty
should not be generated, and should be dropped as an error if received.
<value> ::= <unquoted-string> | <quoted-string>
The value associated with a keyword may be either simple or multiline. A simple value is an <unquoted-string> or <quoted-string> supplied entirely in the same MCP message line as its keyword, and separated from the keyword by a colon and one or more spaces. Every keyword has an associated simple value, even if the keyword names a multiline value.
For example, the message
#$#say 12345 what: "Hi there!" from: Biff to: Betty
contains 3 keyword-value pairs, all with simple values. The message name is say, and the authentication key is 12345. The keywords are what, from, and to; the values associated with these keywords are Hi there!, Biff and Betty respectively.
Simple values containing no spaces, quotation marks, backslashes, colons, or asterisks (in other words, those values matching the <unquoted-string> nonterminal in the grammar given in the appendix) may be sent without quoting; other values (for example, those that contain spaces) must be quoted as strings. However, values have no inherent type. The values 3 and "3" are equivalent. It is up to the handler for a given message to determine whether the value is to be treated as a number or as a string.
Message names and keywords are case-insensitive. The message name mcp-negotiate-can is exactly equivalent to the message name MCP-Negotiate-Can, and the argument keyword what: is identical to WHAT:. Authentication keys are case sensitive, however, and implementations must preserve the case of argument values.
<message-continue> ::= '*' <space> <datatag> <space> <simple-key> ':' ' ' <line> <message-end> ::= ':' <space> <datatag> <datatag> ::= <unquoted-string> <line> ::= <string-char>*
A multiline value is one which is spread over a series of MCP message lines; these values are frequently used to represent blocks of data conveniently represented as lists; for example, the source code to a program, or a block of text lines.
Compliant MCP 2.1 implementations are not required to implement multiline values if they are not necessary to the application for which the implementation is to be used. Specifically, if an implementation is designed to support a fixed set of packages, none of which use multiline values, there is no need to provide support for multilines. If, however, the implementation may at some point be extended to provide support for packages beyond those it was originally designed to support, implementation of multilines is encouraged.
If there is an asterisk after the keyword in a keyword-value pair, the value is multiline. Although a simple value is required syntactically, it will be ignored. (Typically the empty string, "", is used.)
The real value is sent as a series of lines after the first one (hence the name). These lines need not be consecutive; they may be interspersed with other text, including other MCP messages, and lines from different multiline values in the same message may be interspersed. However, the lines within each value must be sent in order. There is no limit on the number of lines in a multiline value.
If there are any multiline values, the message must include a keyword named _data-tag. This, in combination with the value's keyword, will be used to flag subsequent lines. Data tags are case-sensitive (implementations must not vary the case of any alphabetic characters in the tag between the _data-tag argument and the multiline value, or within the multiline value itself), and may be any string of characters matching the <unquoted-string> nonterminal in the MCP grammar.
The values of multiline arguments are supplied in continuation messages, which begin with the literal string #$#*. While these messages have a syntax similar to typical MCP messages, they have some peculiarities:
Once all value lines have been sent for all multiline values in the message, the implementation sends the message-end message: the literal string #$#: followed by the data tag.
Here is an example of a message with a multiline value:
#$#spam 12345 from: Biff text*: "" _data-tag: 9b76 #$#* 9b76 text: This is some sample text. #$#* 9b76 text: #$#* 9b76 text: Note that you don't need to quote strings #$#* 9b76 text: in multiline data. Also, you can include "special" #$#* 9b76 text: characters like quotes. Everything after the #$#* 9b76 text: space after the keyword and colon is considered #$#* 9b76 text: part of the value. #$#* 9b76 text: This means that spaces can also be part of the value. #$#: 9b76
Multiline values lack authentication keys; the data tags are roughly as secure as the authentication key argument on regular MCP messages (that is, not very), and their lifetime is only the length of a multiline message. For this reason, however, implementations should use some care in the choice of multiline value data tags (specifically, the same care taken in selecting authentication keys. See the authentication keys for some guidelines), and should ignore messages for which no matching _data-tag argument has been seen.
Moreover, implementations must ensure that data tags are unique over their lifetimes; that is, an implementation must not generate a new tag matching a previously-generated tag before the message-end message for that tag has been sent.
Multiline values are generally used to represent lists of items; for example, lines of code or quoted text. Implementations should preserve the line divisions implicit in multiline messages so that package implementations may make use of this information.
In general, MCP implementations should be as unobtrusive as possible. If an unrecognized or mangled MCP request is received, the implementation should either silently drop it on the floor, or notify the user in some reasonably unobtrusive way. Similarly, applications should be prepared to handle (by ignoring) unexpected additional arguments on messages. "Mangled" messages here include multiline value messages for which a message-end message has already been seen, or with a keyword whose initial occurrence (in the message having the _data-tag argument) was not followed by an asterisk. Implementations may (and are encouraged to) provide debugging modes which are more verbose than the default silent mode specified here.
In initializing MCP communications, the server and client negotiate version and package support. The negotiation makes use of 2 messages: mcp and mcp-negotiate-can. The former message is sent at the beginning of the session; it must precede ALL other MCP communication. The latter message is used to indicate support for MCP packages.
The mcp message should be the first message sent by the recipient of a connection (usually a MUD server) when a connection initiator (usually a client) connects or reconnects. It indicates that the server is capable of supporting MCP and the MCP versions supported. The message has two arguments: version indicates the minimum protocol version supported by the server and to indicates the maximum protocol version supported by the server. In both cases, the argument value is in the form major.minor, where major and minor should be read as unsigned integers with no leading zeroes. Both arguments are required. Note that MCP 1.0 also supported version advertisement, but not of a range of versions; the names of the arguments for the mcp message were chosen to allow version handshake between version 2.1 and 1.0 implementations (which will simply discard the to argument and decide whether to use MCP based on the version argument).
When a client disconnects from, or reconnects to the server, all stored MCP information about the client should be reset, and a new mcp message sent.
Example:
#$#mcp version: 2.1 to: 2.1
This message indicates the server supports MCP, version 2.1 only.
In this and all version ranges, advertising a range of versions indicates that all versions in the range are supported. For example, a server sending an mcp message with the version parameter set to 1.0 and a to of 2.1 must support MCP version 1.5 if such a version existed; (it doesn't; the only released versions of the MCP specification have versions 1.0 and 2.1; see the historical note in the introduction for more information about implemented versions). If there is any doubt about whether an intermediate version exists or is supported, an implementation should advertise a range including only those versions known to be supported.
On receipt of the mcp message, the client sends an mcp message in reply, with slightly different arguments (the client should not attempt to send any MCP message to the server, including the mcp message itself, until after an mcp message has been received from the server). The message from client to server has 3 arguments: authentication-key, a string to be used as a key on later messages, and version and to, which are defined as above. All three arguments are required.
The authentication-key argument value is a string which is to be stored as a secret on the server and used to tag any further messages from the server to the client. While the level of security provided by this scheme is minimal (especially since the authentication key will be repeatedly transferred across the wire in cleartext), it provides a simple and fairly basic protection against "spoofed" MCP messages. Once the authentication key has been chosen, it is used as the authentication-key argument on all subsequent messages. Implementations should reject any message containing a key which does not match their stored copy. The only messages which may be transmitted without an authentication-key argument are the initial mcp message and the mcp message which sets the authentication key.
Example:
#$#mcp authentication-key:<PHONE_NUMBER>8 version: 1.0 to: 2.1
This message indicates that the client supports MCP, versions 1.0 through 2.1, and indicates that the authentication key for the session is<PHONE_NUMBER>8. Note that while this particular key is composed entirely of digits, the authentication-key argument need not be numeric, and may be any value which matches the syntax of an <unquoted-string>.
In choosing an authentication key, the client should take care to ensure that the key is not easily guessed, as possession of the authentication key (along with the ability to send lines of text to the implementation, an ability possessed by all users on some MUDs) permits the spoofing of MCP messages. In most cases, a spoofed message should be an annoyance at worst. However, it is easy to envision packages based upon MCP in which a spoofed message could be disastrous.
Each side of the connection, once it knows the MCP version range supported by the other, should compare the protocol versions supported by the implementation and the other side; if the supported ranges overlap, the highest version from that overlap should be used. If there is no overlap, the implementations cannot communicate using MCP. Algorithmically:
function mcp-version(client-min,
client-max, server-min,
server-max)
Where client-min, client-max, server-min, and server-max are the minimum and maximum versions from the client and server mcp messages. Version numbers are compared for magnitude by comparing first the major, then the minor part:
function version-geq(v1, v2)
Once a version has been negotiated (and not before), both sides may send other MCP messages. The client may proceed as soon it sends its mcp message, since it has already received the server's mcp message. The server must wait to send any other MCP messages until an mcp message is received from the client.
MCP groups messages into packages. A package is simply a group of messages with a name and version. Generally, a package will be used to implement a particular application: for example, client-local editing of server text. A package name is a hyphen-separated sequence of valid MCP identifiers. While this name is interpreted hierarchically with the leftmost identifier being the most significant, the administration of package naming is, with the exception of the rules below, currently unspecified. As such, package designers must exercise caution in choosing package names so as not to conflict with existing packages (especially for common names, such as edit, for which a number of conflicting implementations can be imagined.) To alleviate this problem, some rules and suggestions apply to package and message names:
Most MCP packages will be application-specific suites of messages to solve a particular problem. However, MCP defines two standard packages. The first of these, the mcp-negotiate package, is a critical part of the MCP startup sequence, and all MCP implementations are required to implement it. The second, the mcp-cord package, allows the creation of multiple communications channels within MCP's single channel. Implementations are strongly suggested, but not required, to provide support for cords. Its presence in the standard reflects this suggestion, and serves as an example of a package built on top of MCP.
Once the server and client have agreed on MCP 2.1 as described in Section 2.4, they negotiate the packages supported by each side and their versions. The server and client inform each other of package capabilities using the mcp-negotiate package, which is itself an MCP package. All MCP 2.1 implementations are assumed to implement at least version 1.0 of this package; they may implement later versions (this document describes version 2.0).
The mcp-negotiate package consists of two messages:
The mcp-negotiate-can message has three arguments: package, a string naming the package, and min-version and max-version, version numbers as above. On receipt of an mcp-negotiate-can message, an implementation should check the package: argument against the implementation's list of supported packages. If the package is known by the implementation, it should compare the min-version and max-version arguments against the versions of the package supported, picking the highest version from the overlap, if any, as in the versioning algorithm described above.
Example:
#$#mcp-negotiate-can 1234 package: edit min-version: 1.0 max-version: 1.0
This message indicates that the sender supports the edit package, version 1.0 only. If the receiver also supports version 1.0 of this package, it may immediately begin sending messages in that package (assuming it has already sent an mcp-negotiate-can message for that package).
Because the mcp-negotiate package is itself a package (the version described here is 2.0) an mcp-negotiate-can message should be sent for the mcp-negotiate package. For a 2.0 implementation, this message should be:
#$#mcp-negotiate-can 1234 package: mcp-negotiate min-version: 1.0 max-version: 2.0
(With the appropriate authentication key, of course.)
Note that no ordering is necessary or imposed on the transmission of mcp-negotiate-can messages. The messages may be thought of as being transmitted in parallel and simultaneously from both the client and the server. Neither need wait for the other to express its ability to perform a particular package before expressing its own ability to perform that package. The reason for this is simple: an implementation knows which packages it supports, and the purpose of the mcp-negotiate-can is to simply inform the other participant of that ability, so that it may begin making use of that package in transmission.
Once an mcp-negotiate-can message has been received for a particular package, an implementation may begin sending messages in that package. An implementation should send mcp-negotiate-can messages for all packages it supports, and may begin sending these messages immediately upon completion of the MCP version negotiation phase. With the exception of the mcp-negotiate package, neither the client nor the server should assume that any package is available on the other until an mcp-negotiate-can message is received for that package.
The mcp-negotiate-end message indicates that mcp-negotiate-can messages have been sent for all packages supported by the endpoint sending the message. The message takes no argument.
Example:
#$#mcp-negotiate-end 1234
This message indicates that the sending endpoint is done sending mcp-negotiate-can messages; that is, it has sent these messages for all packages it supports, and will not send any more. Implementations should ignore any mcp-negotiate messages received after the mcp-negotiate-end message as errors.
To avoid some of the significant potential race conditions lurking in package negotiation, implementations are not permitted to wait for receipt of an mcp-negotiate-end message before sending mcp-negotiate-can messages for packages they support. Implementations are permitted to wait for receipt of mcp-negotiate-end before making use of a package for which the implementation sending mcp-negotiate-end has advertised support, or before processing any MCP messages except mcp-negotiate-can. This permits an implementation to "prefer" some packages over others which support similar, but more limited, functionality. For example, consider an implementation which supports the hypothetical edit, superedit, and gonzoedit packages, and which "prefers" gonzoedit to superedit, and superedit to edit. On receiving this message:
#$#mcp-negotiate-can 1234 package: edit min-version: 1.0 max-version: 1.0
it may wish to wait for a better package before sending a message in the edit package. Since the implementation has not yet received the mcp-negotiate-end message, it's still possible the sending implementation supports superedit or gonzoedit. On receiving a second message,
#$#mcp-negotiate-can 1234 package: superedit min-version: 1.0 max-version: 1.0
it has a better package available, but may still wish to wait. However, on receiving this message:
#$#mcp-negotiate-end 1234
it knows the gonzoedit package will not be available, and it should settle for superedit. Note that while the implementation may wait to send any messages in these packages until receipt of the mcp-negotiate-end message, it may not wait for this message before advertising support for edit, superedit, gonzoedit, and any other packages it supports.
The preceding discussion describes version 2.0 of the mcp-negotiate package, but only version 1.0 of the package is required for MCP 2.1 compliance. There are two differences between version 1.0 and version 2.0 of the mcp-negotiate package:
In general, it is safe for an implementation to assume that an MCP 2.1 implementation with which it is communicating supports version 2.0 of the mcp-negotiate package: because of the way the versioning and error handling for MCP are specified, the additional messages will simply be ignored by a compliant implementation.
A complete startup, between a client supporting the
edit, mcp-cord, and spam
packages, and a server supporting the edit and
mcp-cord packages:
(> : server-to-client, < : client-to-server)
The client compares these versions against its supported versions, 1.0 and 2.1, and chooses 2.1, the maximum of the overlapping version numbers.
The client chooses an authentication key.
The server compares these versions against its supported versions and chooses 2.1, the maximum of the overlapping version numbers.
The client notes that the server supports the mcp-negotiate package.
The client notes that the server supports the edit package.
The server notes that the client supports the mcp-negotiate package.
The server notes that the client supports the mcp-cord package
The server, which does not support the spam package, ignores this.
The server notes that the client supports the edit package.
The client is done sending mcp-negotiate-can messages.
The client notes that the server supports the mcp-cord package.
The server is done sending mcp-negotiate-can messages.
Cords are a mechanism for multiplexing additional communications channels over a single MCP channel. Cords are frequently used to "tie" a server object to a client object. For example, a cord may be used to direct communications between a server object and a window on the client display. Ideally, the plumbing work to deliver cord messages to the appropriate object is invisible to the applications programmer, who should only be concerned with the messages to be sent, not the mechanism involved in assuring that the arrive at the appropriate destination. While cords provide no user-visible functionality, they are an extremely useful tool in implementing applications for which some amount of state is shared between the server and client. The version of the mcp-cord package described here is 1.0; its package name for use in the MCP negotiation process is mcp-cord.
Cords are not, strictly speaking, part of MCP 2.1, and compliant implementations are not required to support them. However, experience has shown that they are generally very useful as a protocol design tool, that many extensions are made significantly easier to construct by the presence of cords, and that they benefit from a fast, low-level implementation. As such, compliant implementations are encouraged to support the mcp-cord package.
Three operations are possible on cords: they may be created, have messages sent along them, and they may be destroyed. Each cord has an associated unique (to the opening participant) identifier and a type. The type is similar to an MCP package name -- it determines the messages which may be sent along a cord, and is used by the recipient of an open request to attach the cord to an appropriate object.
Cords are bidirectional: once a cord is open, messages may be sent along that cord in either direction, and either endpoint may close the cord at any time Implementations should not expect to necessarily receive a cord closed message for a closed cord; this may happen in the case where an implementation disconnects unexpectedly. If an implementation receives a message on a cord which was closed, it should treat the message as an unrecognized MCP message, silently dropping it, or unobtrusively notifying the user.
One MCP message is defined for each cord operation. Any message may be sent from either the server or the client.
Example:
#$#mcp-cord-open 3487 _id: I12345 _type: whiteboard
The _id here, when combined with the connection endpoint which opened this cord, uniquely identifies the cord; however, since the connection endpoint will not be reflected in messages sent on the cord, implementations must take steps to ensure that the identifier provided is unique to a session. To this end, implementations should construct the _id argument using some variation on the following algorithm:
function new-mcp-cord-id()
The goal here is to produce IDs which are guaranteed to be different for a given pair of connection endpoints. As long as the connection endpoints generate IDs in some locally-unique (for the session) fashion, as required in line 1, and noting that any connection supported by MCP has only two endpoints, we need only distinguish the endpoints as "initiator" ("I") and "responder" ("R") to ensure that the transmitted IDs are unique for a session. The definition of "server" and "client" here is based on the position the connection endpoints took in the initial MCP startup process: the server (or "initiator") is the endpoint which sent the first MCP message. Some variation is allowed on this algorithm; as long as an implementation can strictly guarantee that no duplication will occur over the course of a session, it is free to choose any alphanumeric value for the n in the algorithm. Implementations must not assume anything about a received _id value other than that it is unique to a session.
Example:
#$#mcp-cord 3487 _id: I12345 _message: delete-stroke stroke-id: 12321
In this example, the stroke-id argument is an argument to the delete-stroke cord message.
Example:
#$#mcp-cord-closed 3487 _id: I12345
Note that mcp-cord-closed messages need only be sent in one direction, by the endpoint closing the cord, and once the message has been sent, the cord should be assumed to be closed. Implementations should not expect to receive a mcp-cord-closed message in reply. However, due to potential race conditions, an mcp-cord-closed message may be received by an endpoint which has already sent a mcp-cord-closed message for the same cord. As with any message on a closed cord, these messages should be ignored.
Jay Carlson, Roger Crew, Ken Fox, Richard Godard, Dave Kormann, Erik Ostrom, John Ramsdell, Vijay Saraswat, Andrew Wilson
Substantial additional contributions and critical comments by Michael Brundage, William Drury, and Chris Rath.
The following is a somewhat extended BNF grammar for the MCP message format. Terminals in this BNF are quoted (i.e. '#$#'), and nonterminals appear in angle-brackets (i.e. <message>). The special (unquoted) terminal EOL represents an end-of-line, usually a carriage return and newline. The metacharacter | is used to signify alternation, and ::= is used to signify nonterminal expansion. Unquoted spaces in the BNF are for formatting purposes only, and are not syntactically significant.
<message-line> ::= '#$#' <message> EOL <message> ::= <message-start> | <message-continue> | <message-end> <message-start> ::= <message-name> <space> <auth-key> <keyvals> <message-continue> ::= '*' <space> <datatag> <space> <simple-key> ':' ' ' <line> <message-end> ::= ':' <space> <datatag> <message-name> ::= <ident> <auth-key> ::= <unquoted-string> <datatag> ::= <unquoted-string> <keyvals> ::= '' | <space> <keyval> <keyvals> <keyval> ::= <key> ':' <space> <value> <key> ::= <simple-key> | <multiline-key> <simple-key> ::= <ident> <multiline-key> ::= <ident> '*' <value> ::= <unquoted-string> | <quoted-string> <ident> ::= <alpha> <ident-chars> <unquoted-string> ::= <simple-char> | <simple-char> <unquoted-string> <quoted-string> ::= '"' <string-chars> '"' <ident-chars> ::= '' | <ident-char> <ident-chars> <string-chars> ::= '' | <string-char> <string-chars> <line> ::= '' | <line-char> <line> <space> ::= ' ' | ' '<space> <ident-char> ::= <alpha> | <digit> | '-' <string-char> ::= <simple-char> | <space> | '\' <quote-char> | ':' | '*' <line-char> ::= <simple-char> | <quote-char> | <space> | ':' | '*' <quote-char> ::= '"' | '\' <simple-char> ::= <alpha> | <digit> | <other-simple> <other-simple> ::= '-' | '~' | '`' | '!' | '@' | '#' | '$' | '%' | '^' | '&' | '(' | ')' | '=' | '+' | '{' | '}' | '[' | ']' | '|' | ''' | ';' | '?' | '/' | '>' | '<' | '.' | ',' <digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' <alpha> ::= 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' | '_'
Note that whitespace is required in many places, but the amount of whitespace doesn't matter except in <message-continue>, in which any whitespace after the first space after the colon will be considered part of the <line>.


Methods
Public Instance methods
Instantiate the global Active Record observers.
[ show source ]
# File vendor/rails/activerecord/lib/active_record/observer.rb, line 34 34: def instantiate_observers 35: return if @observers.blank? 36: @observers.each do |observer| 37: if observer.respond_to?(:to_sym) # Symbol or String 38: observer.to_s.camelize.constantize.instance 39: elsif observer.respond_to?(:instance) 40: observer.instance 41: else 42: raise ArgumentError, "#{observer} must be a lowercase, underscored class name (or an instance of the class itself) responding to the instance method. Example: Person.observers = :big_brother # calls BigBrother.instance" 43: end 44: end 45: end
Gets the current observers.
[ show source ]
# File vendor/rails/activerecord/lib/active_record/observer.rb, line 29 29: def observers 30: @observers ||= [] 31: end
Activates the observers assigned. Examples:
# Calls PersonObserver.instance ActiveRecord::Base.observers = :person_observer # Calls Cacher.instance and GarbageCollector.instance ActiveRecord::Base.observers = :cacher, :garbage_collector # Same as above, just using explicit class references ActiveRecord::Base.observers = Cacher, GarbageCollector
Note: Setting this does not instantiate the observers yet. instantiate_observers is called during startup, and before each development request.
[ show source ]
# File vendor/rails/activerecord/lib/active_record/observer.rb, line 24 24: def observers=(*observers) 25: @observers = observers.flatten 26: end
Protected Instance methods
Notify observers when the observed class is subclassed.
[ show source ]
# File vendor/rails/activerecord/lib/active_record/observer.rb, line 49 49: def inherited(subclass) 50: super 51: changed 52: notify_observers :observed_class_inherited, subclass 53: end


Related tags: rss weather news web2.0 xml tools ajax software google blog
showing 1 - 10 of 599
« previous | next »
-
Netvibes
-
News feed and RSS reader for Pocket PC and Smartphone - NewsBreak brings news, weather and more to your PDA.
-
Yahoo! Weather
-
Pageflakes - The whole Web at your Fingertips!
-
RSS Feeds World Weather
-
NOAA's National Weather Service - XML warning/watch product data feeds
-
RSS Weather
-
CNN.com
-
Google
-
Protopage v2 released - free AJAX start pages now with RSS news feeds, sticky notes and bookmarks
« previous | next »


< prev index next > modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/encoding.c
Print this page
* the result of transformation can't fit into the encoding we want), or
* -3 if there the last byte can't form a single output char.
*
* The value of @inlen after return is the number of octets consumed
* as the return value is positive, else unpredictable.
- * The value of @outlen after return is the number of ocetes consumed.
+ * The value of @outlen after return is the number of octets consumed.
*/
static int
xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen,
const unsigned char *in, int *inlen) {
size_t icv_inlen, icv_outlen;
* the result of transformation can't fit into the encoding we want), or
* -3 if there the last byte can't form a single output char.
*
* The value of @inlen after return is the number of octets consumed
* as the return value is positive, else unpredictable.
- * The value of @outlen after return is the number of ocetes consumed.
+ * The value of @outlen after return is the number of octets consumed.
*/
static int
xmlUconvWrapper(uconv_t *cd, int toUnicode, unsigned char *out, int *outlen,
const unsigned char *in, int *inlen, int flush) {
const char *ucv_in = (const char *) in;
return(ret);
}
/**
* xmlCharEncFirstLineInt:
- * @handler: char enconding transformation data structure
+ * @handler: char encoding transformation data structure
* @out: an xmlBuffer for the output.
* @in: an xmlBuffer for the input
* @len: number of bytes to convert for the first line, or -1
*
* Front-end for the encoding handler input function, but handle only
return(ret);
}
/**
* xmlCharEncFirstLine:
- * @handler: char enconding transformation data structure
+ * @handler: char encoding transformation data structure
* @out: an xmlBuffer for the output.
* @in: an xmlBuffer for the input
*
* Front-end for the encoding handler input function, but handle only
* the very first line, i.e. limit itself to 45 chars.
}
#endif
/**
* xmlCharEncOutFunc:
- * @handler: char enconding transformation data structure
+ * @handler: char encoding transformation data structure
* @out: an xmlBuffer for the output.
* @in: an xmlBuffer for the input
*
* Generic front-end for the encoding handler output function
* a first call with @in == NULL has to be made firs to initiate the
return(ret);
}
/**
* xmlCharEncCloseFunc:
- * @handler: char enconding transformation data structure
+ * @handler: char encoding transformation data structure
*
* Generic front-end for encoding handler close function
*
* Returns 0 if success, or -1 in case of error
*/
if ((in->buf != NULL) && (in->buf->encoder != NULL)) {
unsigned int unused = 0;
xmlCharEncodingHandler * handler = in->buf->encoder;
/*
* Encoding conversion, compute the number of unused original
- * bytes from the input not consumed and substract that from
+ * bytes from the input not consumed and subtract that from
* the raw consumed value, this is not a cheap operation
*/
if (in->end - in->cur > 0) {
unsigned char convbuf[32000];
const unsigned char *cur = (const unsigned char *)in->cur;
* block of chars out.
*
* Returns 0 if success, -2 if the transcoding fails, or -1 otherwise
* The value of @inlen after return is the number of octets consumed
* as the return value is positive, else unpredictable.
- * The value of @outlen after return is the number of ocetes consumed.
+ * The value of @outlen after return is the number of octets consumed.
*/
static int
UTF8ToISO8859x(unsigned char* out, int *outlen,
const unsigned char* in, int *inlen,
unsigned char const *xlattable) {
*
* Take a block of ISO 8859-* chars in and try to convert it to an UTF-8
* block of chars out.
* Returns 0 if success, or -1 otherwise
* The value of @inlen after return is the number of octets consumed
- * The value of @outlen after return is the number of ocetes produced.
+ * The value of @outlen after return is the number of octets produced.
*/
static int
ISO8859xToUTF8(unsigned char* out, int *outlen,
const unsigned char* in, int *inlen,
unsigned short const *unicodetable) {
< prev index next >


metrics¶
metrics Base¶
Monasca-Statsd based metrics¶
Based on metrics-and-stats blueprint
Usage examples:
from designate.metrics import metrics
@metrics.timed('dot.separated.name')
def your_function():
pass
with metrics.time('dot.separated.name'):
pass
# Increment and decrement a counter.
metrics.counter(name='foo.bar').increment()
metrics.counter(name='foo.bar') -= 10
-
class
designate.metrics.
Metrics
[source]¶ Bases:
object
-
__dict__
= dict_proxy({'timed': <property object at 0x7f0d3e6a4730>, '__dict__': <attribute '__dict__' of 'Metrics' objects>, 'counter': <function counter at 0x7f0d3e61f2a8>, 'timer': <function timer at 0x7f0d3e61f410>, '__doc__': None, '__weakref__': <attribute '__weakref__' of 'Metrics' objects>, '__module__': 'designate.metrics', 'gauge': <function gauge at 0x7f0d3e61f320>, '__init__': <function __init__ at 0x7f0d3e61f1b8>, 'init': <function init at 0x7f0d3e61f230>})¶
-
__init__
()[source]¶ Initialize Monasca-Statsd client with its default configuration. Do not start sending metrics yet.
-
__module__
= 'designate.metrics'¶
-
__weakref__
¶ list of weak references to the object (if defined)
-
init
()[source]¶ Setup client connection or disable metrics based on configuration. This is called once the cfg.CONF is ready.
-
timed
¶
-


--- layout: category title: News category: news --- Stay up to date with the latest news, product announcements, software updates and upcoming events from Leahey Media. Our updates include
This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.


Thank you for stopping by! My name is Joe Romero. I am a designer/ developer based out of New Jersey. If you’re interested in having work done please contact me.
I have experience with: Brand Development, Logo Creation, Web Design, Print Media, Video and Voiceover work.


Interface CollectionInterface
Collection Interface
- Slim\Interfaces\CollectionInterface implements ArrayAccess, Countable, IteratorAggregate
public
|
|
public
|
|
public
|
|
public
|
|
public
|
|
public
|
|
public
|
offsetExists(),
offsetGet(),
offsetSet(),
offsetUnset()
|
count()
|
getIterator()
|


Slush is a scaffolding tool, i.e. a tool to help you generate new project structures to get you up and running with your new project in a matter of seconds.
First you'll have to install NodeJS – if you haven't already.
When NodeJS have been installed you can install the Slush CLI using npm
with:
npm install -g slush
You can verify that all is well by running:
slush -v
Then you should see something like: "[slush] 1.0.1"
in your terminal.
To be able to use Slush to scaffold new projects you'll need a Slush generator. You can find all available generators at the Slush generator search page.
Installing a generator is easily done with npm. For instance, to install the slush-angular
generator you run:
npm install -g slush-angular
If you have followed the steps above, and installed both slush
and the slush-angular
generator, you can generate a new AngularJS project simply by invoking:
slush angular
Answer the questions and bam, there you have it – your first project generated with Slush!


Our office hours are: 9:00am - 5:00pm Monday to Friday
You can reach us by email at any time, please allow 24 hours for a response.
Any emails received during the weekend will be attended to the next working day.


Library StateGraph is a free Modelica package providing components to model discrete event and reactive systems in a convenient way. This package contains the User's Guide for the library and has the following content:
| Name | Description |
|---|---|
| OverView | Overview of library |
| FirstExample | A first example |
| ApplicationExample | An application example |
| ComparisonWithStateGraph2 | Comparison with StateGraph2 |
| ReleaseNotes | Release notes |
| Literature | Literature |
| Contact | Contact |


Currently (4th Q 2021) we use Elastic Email to send campaigns to members. We will change to a different emailer in version 2 at which time this document will be updated.
Currently (4th Q 2021) we use Elastic Email to send campaigns to members. We will change to a different emailer in version 2 at which time this document will be updated.
There is no test environment for Elastic Email. Please do not stray from the steps outlined below.
https
protocol.CMD + C
(CTRL + C
in Windows) to copy it to your clipboard.CMD + V
(CTRL + V
in Windows) to paste the link from your clipboard


PSP is an innovative Austrian company that develops and operates advanced bridge monitoring systems.
PSP's systems use lightweight embedded hardware on-site that requires little infrastructure support.
The on-site hardware connects, via the mobile telephone network, to a server located on our premises that performs analysis, archiving and reporting.
With our systems, clients can monitor the structural health of their bridges (iSHM) and measure heavy goods traffic (iBWIM) from their office.
iBWIM and iSHM give engineers and managers the information they need to make informed decisions about bridge safety and maintenance.
Founded in 2004 as a sister company to Petschacher Consulting, we combine expertise in structural engineering with excellence in embedded systems and data analysis.
Our know-how in these areas has allowed us to develop sensors and data acquisition components that are not only optimised for our structures,
but which are robust, reliable and long term stable.
No less important, our experience in structure inspection gives us the insight into how and where the correct sensors should be employed.
Increasingly, we are applying data analysis techniques and stochastic approaches for modelling both traffic patterns and the evloution of damage in structures.
This is an area in which we have been research active for some time in the academic community and it is now beginning to pay dividends in our commercial work.
As a group, the staff of PSP possess a unique skill set that allows PSP to be a leader in this field.
PSP is a Carinthian company with international sales.
We have a highly qualified international staff and run systems throughout Europe and Asia.
We form part of the network of Carinthian high technology companies and were awarded the 2011 Carinthian Innovation and Development Prize.
PSP is committed to research and development. Since our first monitoring system, iBWIM, was introduced in 2011 we have continuously developed and improved our systems.
In 2018 we launched our Structural Health Monitoring (SHM) system, PSP Logger and are currently expanding our range of precision, low drift sensors.
Our first commercial product, the BAUT infrastructure database, provides a framework within which information about a structure, be it numerical, photographic or descriptive, can be stored and accessed.
BAUT is still in service with the Austrian roads authority, ASFINAG, after 15 years.
We also collaborate with academic and research institutes, both within Carinthia and beyond, to develop novel sensors and apply advanced pattern recognition algorithms.
In addition to our development work we are also active in academic research, and have been members of several research consortia. We continue to publish novel work at academic conferences.
Europe's economic future depends on the smooth transport of goods and vehicles. One of Europe's key competitive advantages is her extensive and well developed infrastructure. Much of the European road bridge infrastructure was built in the 1970's and will soon be entering middle age. In the coming years it will be increasingly prone to failures and large parts of it will need to be replaced.
The economic and environmental costs of replacement and its associated disruption will be great.
The key to maintaining operation and managing maintenance will be monitoring. By observing the structural health of bridges, faults can be detected early and their development tracked.
Decisions about whether to intervene early in the fault's evolution—when repairs will be cheaper, or to postpone to the next scheduled maintenance when traffic disruption will be lower, have significant economic implications.
With quantitative data, engineers can make informed decisions about the need and scheduling of maintenance.
The systems we build at PSP help engineers make informed decisions about the future of bridges. By helping engineers apply proactive and targeted maintenance, our systems help avoid disruption and extend the working life of bridges. At PSP we believe our systems can make a significant contribution to maintaining Europe's road and rail infrastructure.


The following is a comprehensive view of the syntax for MDX in Essbase.
In this document, the syntax for MDX is illustrated using BNF notation.
[<with_section>] SELECT [<axis_specification> [, <axis_specification>...]] [FROM [<cube_specification>]] [WHERE [<slicer_specification> [<dim_props>]] <cube_specification> ::= '[' <ident_or_string>.<ident_or_string> ']' | <delim_ident>.<delim_ident> <delim_ident> ::= '[' <ident> ']' | <ident_or_string> <ident_or_string> ::= ' <ident> ' | <ident>
Note:
<ident> refers to a valid Essbase application/database name. In the cube specification, if there are two identifiers, the first one should be application name and the second one should be database name. For example, all of the following are valid identifiers:
Sample.Basic
[Sample.Basic]
[Sample].[Basic]
'Sample'.'Basic'
<axis_specification> ::= [NON EMPTY] <set> [<dim_props>] ON COLUMNS | ROWS | PAGES | CHAPTERS | SECTIONS | AXIS (<unsigned_integer>) <dim_props> ::= [DIMENSION] PROPERTIES <property> [, <property>...] <slicer_specification> ::= <set> | <tuple> | <member>
Note:
The cardinality of the <set> in the slicer should be 1.
<member> ::= <member-name-specification> | <member_value_expression> <member-name-specification> ::=
A member name can be specified in the following ways:
By specifying the actual name or the alias; for example, Cola, Actual, COGS, and [100].
If the member name starts with number or contains spaces, it should be within braces; for example, [100]. Braces are recommended for all member names, for clarity and code readability.
For attribute members, the long name (qualified to uniquely identify the member) should be used; for example, [Ounces_12] instead of just [12].
By specifying dimension name or any one of the ancestor member names as a prefix to the member name; for example, [Product].[100-10] and [Diet].[100-10] This is a recommended practice for all member names, as it eliminates ambiguity and enables you to refer accurately to shared members.
Note:
Use only one ancestor in the qualification. Essbase returns an error if multiple ancestors are included. For example, [Market].[New York] is a valid name for New York, and so is [East].[New York]. However, [Market].[East].[New York] returns an error.
By specifying the name of a calculated member defined in the WITH section.
For outlines that have duplicate member names enabled, see also MDX Syntax for Specifying Duplicate Member Names and Aliases.
<member_value_expression> ::= Parent ( <member> [,<hierarchy>] ) | <member>.Parent [(<hierarchy>)] | FirstChild ( <member> ) | <member>.FirstChild | LastChild ( <member> ) | <member>.LastChild | PrevMember ( <member> [,<layertype>] ) | <member>.PrevMember [( <layertype> ) ] | NextMember ( <member> [,<layertype>] ) | <member>.NextMember [( <layertype> ) ] | FirstSibling ( <member> [,<hierarchy>]) | <member>.FirstSibling [(<hierarchy>)] | LastSibling ( <member> [,<hierarchy>]) | <member>.LastSibling [(<hierarchy>)] | Ancestor ( <member> , <layer> | <index> [,<hierarchy>] ) | Lead ( <member>, <index> [,<layertype>] [,<hierarchy>] ) | <member>.Lead ( <index> [,<layertype>] [,<hierarchy>] ) | Lag ( <member>, <index> [,<layertype>] [,<hierarchy>] ) | <member>.Lag ( <index> [,<layertype>] [,<hierarchy>] ) | CurrentMember ( <dim_hier> ) | <dim_hier>. CurrentMember | DefaultMember ( <dim_hier> ) | <dim_hier>. DefaultMember | OpeningPeriod ( [<layer> [,<member>]] ) | ClosingPeriod ( [<layer> [,<member>]] ) | Cousin (<member>, <member>) | ParallelPeriod( [<layer>[, <index>[, <member> [,<hierarchy>]]]] ) | Item ( <tuple>, <index> ) | tuple[.Item] ( <index> ) | LinkMember ( <member>, <hierarchy> ) | member.LinkMember ( <hierarchy> ) | DateToMember (<date>, <dim_hier> [ ,<genlev>] ) | StrToMbr (<string_value_expr> [,<dimension>] [, MEMBER_NAMEONLY | <alias_table_name>]) <dim_hier> ::= <dimension> <dimension> :: = <dimension-name-specification> | DIMENSION ( <member> | <layer> ) | <member>.DIMENSION | <layer>.DIMENSION <dimension-name-specification> ::= Same as <member_name-specification> case 1. e.g. Product, [Product] <hierarchy> ::= A hierarchy refers to a root member of an alternate hierarchy, which is always at generation 2 of a dimension. Member value expressions are not allowed as hierarchy arguments. <layertype> ::= GENERATION | LEVEL <layer> ::= <layer-name-specification> | Levels ( <dim_hier>, <index> ) | <dim_hier>.Levels ( <index> ) | Generations ( <dim_hier>, <index> ) | <dim_hier>.Generations ( <index> ) | <member>.Generation | <member>.Level <layer-name-specification> ::=
A layer name can be specified in the following ways:
By specifying the generation or level names; for example, States or Regions.
The generation or level name can be within braces; for example, [Regions]. Using braces is recommended.
By specifying the dimension name along with the generation or level name; for example, Market.Regions and [Market].[States] This naming convention is recommended.
<tuple> ::= <member> | ( <member> [,<member>].. ) | <tuple_value_expression>
A tuple is a collection of member(s) with the restriction that no two members can be from the same dimension. For example, (Actual, Sales) is a tuple. (Actual, Budget) is not a tuple, as both members are from the same dimension.
<tuple_value_expression> ::= CurrentTuple ( <set> ) | <set>.Current | Item ( <set>, <index> ) | <set>[.Item] (<index>)
A set is a collection of tuples where members in all tuples must be from the same dimensions and in the same order.
For example, {(Actual, Sales), (Budget, COGS)} is a set.
{(Actual, Sales), (COGS, [100])} is not a set because the second tuple has members from Scenario and Product dimensions, whereas the first tuple has members from Scenario and Measures dimensions.
{(Actual, Sales). (COGS, Budget)} is not a set because the second tuple has members from Scenario and Measures dimensions, whereas the first tuple has members from Measures and Scenario dimensions (the order of dimensions is different).
Note:
The size of an input set to a function has range between 0 and<PHONE_NUMBER> tuples.
<set> ::= MemberRange ( <member>, <member> [,<layertype>] [,<hierarchy>] ) | <member> : <member> | { <tuple>|<set> [, <tuple>|<set>].. } | ( <set> ) | <set_value_expression> <set_value_expression> ::= | Members ( <dim_hier> ) | <dim_hier>.Members | Members ( <layer> ) | <layer>.Members | Children ( <member> ) | <member>.Children | CrossJoin ( <set> , <set> ) | Union ( <set> , <set> [,ALL] ) | Intersect ( <set> , <set> [,ALL]) | Except ( <set> , <set> [,ALL]) | Extract ( <set> , <dim_hier> [, <dim_hier>].. ) | Head ( <set> [, <index>]) | Subset ( <set> , <index> [,index]) | Tail ( <set> [,index]) | Distinct ( <set> ) | Siblings ( <member> [, <selection_flags>, [INCLUDEMEMBER|EXCLUDEMEMBER]] ) | <member>.Siblings | Descendants ( <member> , [{<layer>|<index>}[, <Desc_flags>]] ) | PeriodsToDate ( [<layer>[, <member> [,<hierarchy>]]] ) | LastPeriods ( <index>[, <member> [,<hierarchy>]] ) | xTD ( [<member>] ) where xTD could be {HTD|YTD|STD|PTD|QTD|MTD|WTD|DTD} | Hierarchize ( <set> [,POST] ) | Filter ( <set> , <search_condition> ) | Order ( <set>, <value_expression> [,BASC | BDESC] ) | TopCount ( <set> , <index> [,<numeric_value_expression>] ) | BottomCount ( <set> , <index> [,<numeric_value_expression>] ) | TopSum ( <set> , <numeric_value_expression> , <numeric_value_expression> ) | BottomSum ( <set> , <numeric_value_expression> , <numeric_value_expression> ) | TopPercent ( <set> , <percentage> , <numeric_value_expression> ) | BottomPercent ( <set> , <percentage> , <numeric_value_expression> ) | Generate ( <set> , <set> [, [ALL]] ) | DrilldownMember ( <set> , <set>[, RECURSIVE] ) | DrillupMember ( <set> , <set> ) | DrilldownByLayer ( <set> [, {<layer>|<index>] ) | DrilldownLevel ( <set> [, {<layer>|<index>] ) | DrillupByLayer ( <set> [, <layer>] ) | DrillupLevel ( <set>[, <layer>] ) | WithAttr ( <member> , <character_string_literal>, <value_expression> ) | WithAttrEx ( <member> , <character_string_literal>, <value_expression>, ANY, <tuple>|<member> [, <tuple>|<member>] ) | Attribute ( <member> ) | AttributeEx ( <member>, ANY, <tuple>|<member> [, <tuple>|<member>] ) | Uda ( <dimension> | <member> , <string_value_expression> ) | RelMemberRange ( <member>, <prevcount>, <nextcount>, [,<layertype>] [,<hierarchy>] ) | Ancestors ( <member>, <layer>|<index> ) | <conditional_expression>
Note:
<conditional_expression> is expected to return a <set> in the above production.
<Desc_flags> ::= SELF | AFTER | BEFORE | BEFORE_AND_AFTER | SELF_AND_AFTER | SELF_AND_BEFORE | SELF_BEFORE_AFTER | LEAVES <selection_flags> ::= LEFT | RIGHT | ALL <value_expression> ::= <numeric_value_expression> | <string_value_expression> <numeric_value_expression> ::= <term> | <numeric_value_expression> + <term> | <numeric_value_expression> - <term> <term> ::= <factor> | <term> * <factor> | <term> / <factor> <factor> ::= [+ | -]<numeric_primary> <numeric_primary> ::= <value_expr_primary> | <numeric_value_function> | <mathematical_function> | <date_function>
Note:
The data type of <value_expr_primary> in the above production must be numeric.
<base> ::= <numeric_value_expression> <power> ::= <numeric_value_expression> <mathematical_function> ::= Abs ( <numeric_value_expression> ) | Exp ( <numeric_value_expression> ) | Factorial ( <index> ) | Int ( <numeric_value_expression> ) | Ln ( <numeric_value_expression> ) | Log ( <numeric_value_expression> [, <base>] ) | Log10 ( <numeric_value_expression> ) | Mod ( <numeric_value_expression> , <numeric_value_expression> ) | Power ( <numeric_value_expression> , <power> ) | Remainder ( <numeric_value_expression> ) | Stddev ( <set> [,<numeric_value_expression> [,IncludeEmpty] ] ) | Stddevp ( <set> [,<numeric_value_expression> [,IncludeEmpty] ] ) | Round ( <numeric_value_expression> , <index> ) | Truncate ( <numeric_value_expression> ) <date_function> ::= DateRoll(<date>, <date_part>, <index>) | DateDiff(<date>, <date>, <date_part>) | DatePart(<date>, <date_part>) | Today() | TodateEx(<date_format_string>, <string>) | GetFirstDate(<member>) | GetLastDate(<member>) | UnixDate(<numeric_value_expression>) | GetFirstDay(<date>, <date_part>) | GetLastDay(<date>, <date_part>) | GetNextDay(<date>, <week-day-specification>, [0|1] ) | GetRoundDate(<date>, <date_part>)
The <date> argument is a number representing the input date. The number is the number of seconds elapsed since midnight, January 1, 1970. To retrieve this number, use any of the following functions: Today(), TodateEx(), GetFirstDate(), GetLastDate().
<date_part> ::= DP_YEAR | DP_QUARTER | DP_MONTH | DP_WEEK | DP_DAY | DP_DAYOFYEAR | DP_WEEKDAY
Note:
DP_DAYOFYEAR and DP_WEEKDAY are not valid arguments in functions DateRoll and DateDiff.
<week-day-specification> ::= 1 | 2 | 3 | 4 | 5 | 6 | 7 e.g. 1 implying Sunday, 7 implying Saturday <date_format_string> ::= "mon dd yyyy" | "Month dd yyyy" | "mm/dd/yy" | "mm/dd/yyyy" | "yy.mm.dd" | "dd/mm/yy" | "dd.mm.yy" | "dd-mm-yy" | "dd Month yy" | "dd mon yy" | "Month dd, yy" | "mon dd, yy" | "mm-dd-yy" | "yy/mm/dd" | "yymmdd" | "dd Month yyyy" | "dd mon yyyy" | "yyyy-mm-dd" | "yyyy/mm/dd" | "Long format" | "Short format" <string_value_expression> ::= <string_value_primary> | FormatDate (<date>, <date_format_string>) | Concat (<string_value_expression> [<, string_value_expression> ...]) | Left(<string_value_expression>, <length>) | Right(<string_value_expression>, <length>) | Substring(<string_value_expression>, <index> [, <index>]) | Upper(<string_value_expression>) | Lower (<string_value_expression>) | RTrim(<string_value_expression>) | LTrim(<string_value_expression>) | NumToStr(<value_expr_primary>) | EnumText(<textlistname> | <member>, <numeric_value_expression>) <value_expr_primary> ::= <unsigned_numeric_literal> | ( <numeric_value_expression> ) | <tuple>[.RealValue] | <member>[.RealValue] | <tuple> [.Value] | <member>[.Value] | CellValue() | <property> | <conditional_expression> | MISSING <string_value_primary> ::= <character_string_literal> | <string_property>
Notes
<conditional_expression> is expected to return a numeric value in the above production.
String literals are delimited by double quotes(").
<conditional_expression> ::= <if_expression> | <case_expression> | CoalesceEmpty ( <numeric_value_expression> , <numeric_value_expression>) <case_expression> ::= <simple_case> | <searched_case> <if_expression> ::= IIF ( <search_condition>, <true_part>, <false_part> ) <true_part> ::= <value_expression> | <set> <false_part> ::= <value_expression> | <set> <simple_case> ::= Case <case_operand> <simple_when_clause>... [ <else_clause> ] END <simple_when_clause> ::= WHEN <when_operand> THEN <result> <else_clause> ::= ELSE <value_expression> | <set> <case_operand> ::= <value_expression> <when_operand> ::= <value_expression> <result> ::= <value_expression> | <set> <searched_case> ::= Case <searched_when_clause>... [ <else_clause> ] END <searched_when_clause> ::= WHEN <search_condition> THEN <result> <numeric_value_function> ::= Avg ( <set> [, <numeric_value_expression>] [, IncludeEmpty] ) | Max ( <set> [, <numeric_value_expression>]) | Min ( <set> [, <numeric_value_expression>]) | Sum ( <set> [, <numeric_value_expression>]) | NonEmptyCount ( <set> [, <numeric_value_expression>]) | Count ( <set> [, IncludeEmpty] ) | Todate ( <string_value_expression> , <string_value_expression> ) | Ordinal (<layer>) | Aggregate (<set> [,<member-name-specification>]) | Rank (<member_or_tuple>, <set> [,<numeric_value_expression> [, <rank_flags>]]) | NTile (<member_or_tuple>, <set>, <index>, <numeric_value_expression>) | Percentile (<set>, <numeric_value_expression>, <numeric_value_expression>) | Median (<set>, <numeric_value_expression>) | Len (<string_value_expression>) | InStr (<index>, <string_value_expression>, <string_value_expression>, <numeric_value_expression>) | StrToNum (<string_value_expression>) | EnumValue(<enum_string>) | JulianDate(<date>)
Note:
The <member-name-specification> in Aggregate function should refer to an Accounts dimension member name.
Note:
<enum_string> represents an enumerated string. It should be in the following format. The member should refer to a member of type text.
<enum_string> ::= <textlist-name-specification>.<character_string_literal> | <member>.<character_string_literal> <textlist-name-specification> ::= Same as <member_name-specification> case 1. The text list name specification should refer to the name of a text list object. e.g. AccountStatus, [AccountStatus] <member_or_tuple> ::= <member> | <tuple> <index> ::= <numeric_value_expression>
Note:
The input <index> argument has range between -2147483647 and<PHONE_NUMBER>.
<percentage> ::= <numeric_value_expression> <search_condition> ::= <bool_term> | <search_condition> OR <bool_term> <bool_term> ::= <bool_factor> | <bool_term> AND <bool_factor> <bool_factor> ::= <bool_primary> | NOT <bool_primary> <bool_primary> ::= <value_expression> [=|>|<|<>|>=|<=] <value_expression> | <property> IN <member>|<character_string_literal> | <property> | IsEmpty ( <value_expression> ) | ( <search_condition> ) | IsSibling(<member>,<member> [, INCLUDEMEMBER]) | IsLeaf(<member>) | IsGeneration(<member>,<index>) | IsLevel(<member>,<index>) | IsAncestor(<member>,<member> [, INCLUDEMEMBER]) | IsChild(<member>,<member> [, INCLUDEMEMBER]) | IsUda (<member>, <string_value_expression>) | IsAccType (<member>, <AcctTag>) | Is ( <member> , <member> ) | <member> Is <member> | IsValid (<member> | <tuple> | <set> | <layer> | <property>) | Contains (<member_or_tuple>, <set>)
Note:
Only properties with boolean values can be used as <bool_primary>.
<AcctTag> ::= FIRST | LAST | AVERAGE | EXPENSE | TWO-PASS <rank_flags> ::= ORDINALRANK | DENSERANK | PERCENTRANK <with_section> ::= WITH <frml_spec> <frml_spec> ::= <single_frml_spec> | <frml_spec> <single_frml_spec> <single_frml_spec> ::= <set_spec> | <perspective_specification> | <member_specification> <set_spec> ::= SET <set_name> AS ' <set> ' <set_name> ::=
The name of the set to be defined. The name cannot be same as any names/aliases of database members, generation/level names, or UDA names.
<perspective_specification> ::= PERSPECTIVE REALITY | <tuple> FOR <dimension-name-specification> <member_specification> ::= MEMBER <member_name> AS ' <nonempty_specification> <numeric_value_expression> ' [, <solve_order_specification>] <member_name> ::= <dimension-name-specification>.<calculated member name> <calculated member name> ::=
Names used for calculated members cannot be the same as any names/aliases of database members, generation/level names, or UDA names.
<solve_order_specification> ::= SOLVE_ORDER = <unsigned_integer> <property> ::= <member>.<property_specification> | <dim_hier>.<property_specification> | <property_specification>
Note:
The last two alternatives in the above rule can be used only inside the DIMENSION PROPERTIES section.
For example, assume an axis has 2 dimensions, Product and Market. Using DIMENSION PROPERTIES Gen_number, [Product].level_number, the generation number will be present in the output for the members of both dimensions, whereas the level number will be present only for the members of the Product dimension.
Within a value expression, [Product].Gen_number refers to the generation number of the member named [Product].
[Product].CurrentMember.Gen_number refers to the generation number of the current member of the [Product] dimension.
For example,
Filter ([Product].Members, [Product].Gen_number > 1)
returns an empty set. Product.Generation is 1, so the search condition fails for each tuple of [Product].Members.
Filter ([Product].Members, [Product].CurrentMember.Gen_number > 1)
returns all members of Product dimension except the top dimension member, [Product].
<string_property> ::= <member>.<property_specification>
Note:
The above rule specifies string properties such as MEMBER_NAME, MEMBER_ALIAS.
<property_specification> ::= MEMBER_NAME | MEMBER_ALIAS | GEN_NUMBER | LEVEL_NUMBER | <dimension-name-specification> | <uda-specification>
Note:
The <dimension-name-specification> in <property_specification> should be an attribute dimension-name specification. The attribute dimension names are treated as properties of members from their corresponding base dimensions.
<uda-specification> ::=
The <uda-specification> specifies a User Defined Attribute(UDA). UDA properties are Boolean-valued properties. A TRUE value indicates presence of a UDA for a member. For example,
Filter (Market.Members, Market.CurrentMember.[Major Market])
returns the Market dimension members tagged with "Major Market" UDA in the outline.
For more discussion of properties, see About MDX Properties.
The following rule describes the syntax for Essbase outline formulas in aggregate storage applications.
<formula_specification> ::= <nonempty_specification> <numeric_value_expression> <nonempty_specification> ::= NONEMPTYMEMBER <nonempty_member_list> | NONEMPTYTUPLE ( <nonempty_member_list> ) <nonempty_member_list> ::= <nonempty_member_name> | <nonempty_member_name> [ , <nonempty_member_list> ] <nonempty_member_name> ::= An Essbase member name or a calculated member name (only when used in another calculated member).
Note:
The member name (or member names when multiple names are specified) in a NONEMPTYMEMBER directive should belong to the same dimension as the calculated member or formula member in which it is specified.
<signed_numeric_literal> ::= [+|-] <unsigned_numeric_literal> <unsigned_numeric_literal> ::= <exact_numeric_literal> | <approximate_numeric_literal> <exact_numeric_literal> ::= <unsigned_integer>[.<unsigned_integer>] | <unsigned_integer>. | .<unsigned_integer> <unsigned_integer> ::= {<digit>}... <approximate_numeric_literal> ::= <mantissa>E<exponent> <mantissa> ::= < exact_numeric_literal> <exponent> ::= [<sign>]<unsigned_integer> <digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
Note:
Numbers can also be input in scientific notation (mantissa/exponent), using the E character.
<character_string_literal> ::= <quote>[<character_representation>...] <quote> <character_representation> ::= <nonquote_character> | <quote_symbol> <nonquote_character> ::= Any character in the character set other than <quote> <quote_symbol> ::= <quote> <quote> <quote> ::= " The following is the syntax for Format Strings in Essbase: MdxFormat( string_value_expression )


I'm Becky, I am interested in perhaps blogging about the experience of reentering the workforce after taking time to raise my kids. I think it would be helpful to other women in the same boat if not a little cathartic for me to work through how this goes as well. Since I am running out of website ideas, this is what I came up with for an assignment.