| < Day Day Up > |
10.2 Fuzzy Logic BasicsNow that you have an idea of what fuzzy logic is all about and how you can use it in games, let's take a close look at how fuzzy logic works and is implemented. If the concept of fuzzy logic is still a little, well, fuzzy to you at this point, don't worry. The concepts will become much clearer as we go over the details in the next few sections. 10.2.4 OverviewThe fuzzy control or inference process comprises three basic steps. Figure 10-1 illustrates these steps. Figure 10-1. Fuzzy process overviewThe first part of the process is called the fuzzification process. In this step, a mapping process converts crisp data (real numbers) to fuzzy data. This mapping process involves finding the degree of membership of the crisp input in predefined fuzzy sets. For example, given a person's weight in pounds, we can find the degree to which the person is underweight, overweight, or at an ideal weight. Once you have expressed all the inputs to the system in terms of fuzzy set membership, you can combine them using logical, fuzzy rules to determine the degree to which each rule is true. In other words, you can find the strength of each rule or the degree of membership in an output, or action, fuzzy set. For example, given a person's weight and activity level as input variables, we can define rules that look something such as the following:
These rules combine the fuzzy input variables using logical operators to yield a degree of membership, or degree or truth, of the corresponding output action, which in this case is the recommendation to engage in frequent exercise or go on a moderate diet. Often, having a fuzzy output such as frequent exercise is not enough. We might want to quantify the amount of exercise—for example, three hours per week. This process of taking fuzzy output membership and producing a corresponding crisp numerical output is called defuzzification. Let's consider each step in more detail. 10.2.5 FuzzificationInput to a fuzzy system can originate in the form of crisp numbers. These are real numbers quantifying the input variables—for example, a person weighs 185.3 pounds or a person is 6 feet 1 inch tall. In the fuzzification process we want to map these crisp values to degrees of membership in qualitative fuzzy sets. For example, we might map 185.3 pounds to slightly overweight and 6 feet 1 inch to tall. You achieve this type of mapping using membership functions, also called characteristic functions. 10.2.1 Membership FunctionsMembership functions map input variables to a degree of membership, in a fuzzy set, between 0 and 1. If the degree of membership in a given set is 1, we can say the input for that set is absolutely true. If the degree is 0, we can say for that set the input is absolutely false. If the degree is somewhere between 0 and 1, it is true to a certain extent—that is, to a degree. Before looking at fuzzy membership functions, let's consider the membership function for Boolean logic. Figure 10-2 illustrates such a function. Figure 10-2. Boolean logic membership functionHere we see that input values lower than x0 are mapped to false, while values higher than x0 are mapped to true. There is no in-between mapping. Going back to the weight example, if x0 equals 170 pounds, anyone weighing more than 170 pounds is overweight and anyone weighing less than 170 pounds is not overweight. Even if a person weighs 169.9 pounds, he still is considered not overweight. Fuzzy membership functions enable us to transition gradually from false to true, or from not overweight to overweight in our example. You can use virtually any function as a membership function, and the shape usually is governed by desired accuracy, the nature of the problem being considered, experience, and ease of implementation, among other factors. With that said, a handful of commonly used membership functions have proven useful for a wide variety of applications. We'll discuss those common membership functions in this chapter. Consider the grade function illustrated in Figure 10-3. Figure 10-3. Grade membership functionHere you can see the gradual transition from 0 to 1. The range of x-values for which this function applies is called its support. For values less than x0, the degree of membership is 0 or absolutely false, while for values greater than x1, the degree is 1 or absolutely true. Between x0 and x1, the degree of membership varies linearly. Using the point-slope equation for a straight line, we can write the equation representing the grade membership function as follows: Going back to the weight example, let's say this function represents the membership for overweight. Let x0 equal 175 and x1 equal 195. If a person weighs 170 pounds, he is overweight to a degree of 0—that is, he is not overweight. If he weighs 185 pounds, he is overweight to a degree of 0.5—he's somewhat overweight. Typically, we're interested in the degree to which an input variable falls within a number of qualitative sets. For example, we might want to know the degree to which a person is overweight, underweight, or at an ideal weight. In this case, we could set up a collection of sets, as illustrated in Figure 10-4. Figure 10-4. Fuzzy sets
With this sort of collection, we can calculate a given input value's membership in each of the three sets—underweight, ideal, and overweight. We might, for a given weight, find that a person is underweight to a degree of 0, ideal to a degree of 0.75, and overweight to a degree of 0.15. We can infer in this case that the person's weight is substantially ideal—that is, to a degree of 75%. The triangular membership function shown in Figure 10-4 is another common form of membership function. Referring to Figure 10-5, you can write the equation for a triangular membership function as follows: Figure 10-5. Triangular membership functionFigure 10-4 also shows a reverse-grade membership function for the underweight set. Referring to Figure 10-6, you can write the equation for the reverse grade as follows: Figure 10-6. Reverse grade membership functionAnother common membership function is the trapezoid function, as shown in Figure 10-7. Figure 10-7. Trapezoid membership functionYou can write the trapezoid function as follows: Setting up collections of fuzzy sets for a given input variable, as shown in Figure 10-4, is largely a matter of judgment and trial and error. It's not uncommon to tune the arrangement of set membership functions to achieve desirable or optimum results. While tuning, you can try different shapes for each fuzzy set, or you can try using more or fewer fuzzy sets. Some fuzzy logic practitioners recommend the use of seven fuzzy sets to fully define the practical working range of any input variable. Figure 10-8 illustrates such an arrangement. Figure 10-8. Seven fuzzy setsThe seven fuzzy sets shown in Figure 10-8 are center, near right, right, far right, near left, left, and far left. These categories can be anything, depending on your problem. For example, to represent the alignment of player and nonplayer characters in your role-playing game, you might have fuzzy sets such as neutral, neutral good, good, chaotic good, neutral evil, evil, and chaotic evil. Notice that each set in Figures 10-4 and 10-8 overlaps immediately adjacent sets. This is important for smooth transitions. The generally accepted rule of thumb is that each set should overlap its neighbor by about 25%. The membership functions we discussed so far are the most commonly used; however, other functions sometimes are employed when higher accuracy or nonlinearity is required. For example, some applications use Gaussian curves, while others use S-shaped curves. These are illustrated in Figure 10-9. For most applications and games, the piecewise linear functions discussed here are sufficient. Figure 10-9. Examples of other membership functionsExample 10-1 shows how the various membership functions we've discussed might look in code. Example 10-1. Fuzzy membership functionsdouble FuzzyGrade(double value, double x0, double x1) { double result = 0; double x = value; if(x <= x0) result = 0; else if(x >= x1) result = 1; else result = (x/(x1-x0))-(x0/(x1-x0)); return result; } double FuzzyReverseGrade(double value, double x0, double x1) { double result = 0; double x = value; if(x <= x0) result = 1; else if(x >= x1) result = 0; else result = (-x/(x1-x0))+(x1/(x1-x0)); return result; } double FuzzyTriangle(double value, double x0, double x1, double x2) { double result = 0; double x = value; if(x <= x0) result = 0; else if(x == x1) result = 1; else if((x>x0) && (x<x1)) result = (x/(x1-x0))-(x0/(x1-x0)); else result = (-x/(x2-x1))+(x2/(x2-x1)); return result; } double FuzzyTrapezoid(double value, double x0, double x1, double x2, double x3) { double result = 0; double x = value; if(x <= x0) result = 0; else if((x>=x1) && (x<=x2)) result = 1; else if((x>x0) && (x<x1)) result = (x/(x1-x0))-(x0/(x1-x0)); else result = (-x/(x3-x2))+(x3/(x3-x2)); return result; } To determine the membership of a given input value in a particular set, you simply call one of the functions in Example 10-1, passing the value and parameters that define the shape of the function. For example, FuzzyTrapezoid(value, x0, x1, x2, x3) determines the degree of membership of value in the set defined by x0, x1, x2, x3 with a shape, as shown in Figure 10-7. 10.2.2 HedgesHedge functions are sometimes used to modify the degree of membership returned by a membership function. The idea behind hedges is to provide additional linguistic constructs that you can use in conjunction with other logical operations. Two common hedges are VERY and NOT_VERY, which are defined as follows: Here, Truth(A) is the degree of membership of A in some fuzzy set. Hedges effectively change the shape of membership functions. For example, these hedges applied to piecewise linear membership functions will result in the linear portions of those membership functions becoming nonlinear. Hedges are not required in fuzzy systems. You can construct membership functions to suit your needs without the additional hedges. We mention them here for completeness, as they often appear in fuzzy logic literature. 10.2.6 Fuzzy RulesAfter fuzzifying all input variables for a given problem, what we'd like to do next is construct a set of rules, combining the input in some logical manner, to yield some output. In an if-then style rule such as if A then B, the "if A" part is called the antecedent, or the premise. The "then B" part is called the consequent, or conclusion. We want to combine fuzzy input variables in a logical manner to form the premise, which will yield a fuzzy conclusion. The conclusion effectively will be the degree of membership in some predefined output fuzzy set. 10.2.3 Fuzzy AxiomsIf we're going to write logical rules given fuzzy input, we'll need a way to apply the usual logical operators to fuzzy input much like we would do for Boolean input. Specifically, we'd like to be able to handle conjunction (logical AND), disjunction (logical OR), and negation (logical NOT). For fuzzy variables, these logical operators typically are defined as follows: Here, again, Truth(A) means the degree of membership of A in some fuzzy set. This will be a real number between 0 and 1. The same applies for Truth(B) as well. As you can see, the logical OR operator is defined as the maximum of the operands, the AND operator is defined as the minimum of the operands, and NOT is simply 1 minus the given degree of membership. Let's consider an example. Given a person is overweight to a degree of 0.7 and tall to a degree of 0.3, the logical operators defined earlier result in the following: In code, these logical operations are fairly trivial, as shown in Example 10-1. Example 10-2. Fuzzy logical operator functionsdouble FuzzyAND(double A, double B) { return MIN(A, B); } double FuzzyOR(double A, double B) { return MAX(A, B); } double FuzzyNOT(double A) { return 1.0 - A; } These are not the only definitions used for AND, OR, and NOT. Some specific applications use other definitions—for example, you can define AND as the product of two degrees of membership, and you can define OR as the probabilistic-OR, as follows: Some third-party fuzzy logic tools even facilitate user-defined logical operators, making the possibilities endless. For most applications, however, the definitions presented here work well. 10.2.4 Rule EvaluationIn a traditional Boolean logic application, rules such as if A AND B then C evaluate to absolutely true or false 1 or 0. After reading the previous section, you can see that this clearly is not the case using fuzzy logic. A AND B in fuzzy logic can evaluate to any number between 0 and 1, inclusive. This fact makes a fundamental difference in how fuzzy rules are evaluated versus Boolean logic rules. In a traditional Boolean system, each rule is evaluated in series until one evaluates to true and it fires, so to speak—that is, its conclusion is processed. In a fuzzy rules system, all rules are evaluated in parallel. Each rule always fires; however, they fire to various degrees, or strengths. The result of the logical operations in each rule's premise yields the strength of the rule's conclusion. In other words, the strength of each rule represents the degree of membership in the output fuzzy set. Let's say you have a video game and are using a fuzzy system to evaluate whether a creature should attack a player. The input variables are range, creature health, and opponent ranking. The membership functions for each variable might look something like those shown in Figure 10-10. Figure 10-10. Input variable membership functionsThe output actions in this example can be flee, attack, or do nothing. We can write some rules that look something like the following: You can set up several more rules to handle more possibilities. In your game, all these rules would be evaluated to yield a degree of membership for each output action. Given specific degrees for the input variables, you might get outputs that look something like this: In code, evaluation of these rules would look something like that shown in Example 10-1, where you can see a distinct difference from traditional if-then style rules. Example 10-3. Fuzzy rulesdegreeAttack = MIN(MIN (degreeMelee, degreeUninjured), 1.0 - degreeHard); degreeDoNothing = MIN ( (1.0 - degreeMelee), degreeUninjured); degreeFlee = MIN (MIN ((1.0 - degreeOutOfRange), (1.0 - degreeUninjured)), (1.0 - degreeWimp)); The output degrees represent the strength of each rule. The easiest way to interpret these outputs is to take the action associated with the highest degree. In this example, the resulting action would be to flee. In some cases, you might want to do more with the output than execute the action with the highest degree. For example, in the threat assessment case we discussed earlier in this chapter, you might want to use the fuzzy output to determine the number, a crisp number, of defensive units to deploy. To get a crisp number as an output, you have to defuzzify the results from the fuzzy rules. 10.2.7 DefuzzificationDefuzzification is required when you want a crisp number as output from a fuzzy system. As we mentioned earlier, each rule results in a degree of membership in some output fuzzy set. Let's go back to our previous example. Say that instead of determining some finite action—do nothing, flee, or attack—you also want to use the output to determine the speed to which the creature should take action. For example, if the output action is to flee, does the creature walk away or run away, and how fast does it go? To get a crisp number, we need to aggregate the output strengths somehow and we need to define output membership functions. For example, we might have output membership functions such as those shown in Figure 10-11. Figure 10-11. Output fuzzy setsWith the numerical output we discussed already—0.2 degree attack, 0.4 degree do nothing, and 0.7 degree flee—we'd end up with a composite membership function, as shown in Figure 10-12. Figure 10-12. Output membership functionTo arrive at such a composite membership function, each output set is truncated to the output degree of membership for that set as determined by the strength of the rules. Then all output sets are combined using disjunction. At this point, we still have only an output membership function and no single crisp number. We can arrive at a crisp number from such an output fuzzy set in many ways. One of the more common methods involves finding the geometric centroid of the area under the output fuzzy set and taking the corresponding horizontal axis coordinate of that center as the crisp output. This yields a compromise between all the rules—that is, the single output number is a weighted average of all the output memberships. To find the center of area for such an output function, you have to integrate the area under the curve using numerical techniques. Or you can consider it a polygon and use computational geometry methods to find the center. There are other schemes as well. In any case, finding the center of area is computationally expensive, especially considering the large number of times such a calculation would be performed in a game. Fortunately, there's an easier way that uses so-called singleton output membership functions. A singleton output function is really just a spike and not a curve. It is essentially a predefuzzified output function. For our example, we can assign speeds to each output action, such as -10 for flee, 1 for do nothing, and 10 for attack. Then, the resulting speed for flee, for example, would be the preset value of -10 times the degree to which the output action flee is true. In our example, we'd have -10 times 0.7, or -7 for the flee speed. (Here, the negative sign simply indicates flee as opposed to attack.) Considering the aggregate of all outputs requires a simple weighted average rather than a center of gravity calculation. In general, let m be the degree to which an output set is true and let x be the crisp result, singleton, associated with the output set. The aggregate, defuzzified output would then be: In our example, we might have something such as: Such an output when used to control the motion of the creature would result in the creature fleeing, but not necessarily in earnest. To reinforce all the concepts we've discussed so far, let's consider a few examples in greater detail. |
| < Day Day Up > |


Theming & Customization
Shortly after the 2.0 release Octopress added the source/_includes/custom
directory. If you don’t have this, you’ll want to update because it’s really nice.
source/
_includes/ # Main layout partials
custom/ # <- Customize head, header, navigation, footer, and sidebar here
asides/ # Theme sidebar partials
post/ # post metadata, sharing & comment partials
_layouts/ # layouts for pages, posts & category archives
Changing the
If you want to add to the
take a look at /source/_includes/custom/head.html
.
1 2 3 |
|
Here you can easily change or remove the Google Webfonts, insert javascripts, etc.
Changing the sidebar
Octopress integrates with some 3rd party services like Twitter, Pinboard and Delicious which appear in the sidebar.
In the _config.yml
you can rearrange these, create custom sidebars for each layout, and add your own sidebar sections.
1 2 3 4 |
|
If you want to add a section to your sidebar, create a new file in source/_includes/custom/asides/
.
Since many people probably want to add an About Me section, there’s already an about.html
file in there waiting to be added. Here’s a look.
1 2 3 4 |
|
Whenever you add a section to the sidebar, follow this pattern, with a

block and an

for a title. To add it to the sidebar, edit the _config.yml
and add it to the list of asides.
1 2 3 4 |
|
In the configuration above I’ve added the about page to the blog index and post pages. Since page_asides
isn’t being set, it will inherit from the default list.
Changing the Header, Navigation & Footer
These are sections of the site that are most likely to be customized. You can edit each in /source/_includes/custom/
and your changes will be preserved across updates.
Changing the Header
The header title and subtitle should be configured in the _config.yml
If you want to make other changes to the header, edit /source/_includes/custom/header.html
which looks like this:
1 2 3 4 5 6 |
|
Changing the Navigation
To change or add links to the main navigation, edit /source/_includes/custom/navigation.html
which looks like this:
1 2 3 4 |
|
The href
for each link begins with {{ root_url }}
(this helps Octopress write urls differently if a site is deployed to a subdirectory).
If you’re deploying your site to a subdirectory like yoursite.com/octopress
you’ll want to add this to any links you add.
Changing the Footer
You can customize the footer in source/_includes/custom/footer.html
which looks like this:
1 2 3 4 |
|
Change this however you like, but be cool and keep the Octopress link in there.


The Variable task provides a mutable property to Ant and works much like variable assignment in Java. This task is similar to the standard Ant Property task, except that THESE PROPERTIES ARE MUTABLE. While this goes against the standard Ant use of properties, occasionally it is useful to be able to change a property value within the build. In general, use of this task is DISCOURAGED, and the standard Ant Property should be used if possible. Having said that, in real life I use this a lot.
Variables can be set individually or loaded from a standard properties file. A 'feature' of variables is that they can override properties, but properties cannot override variables. So if an already established property exists, its value can be reassigned by use of this task.
Table 8.1. Variable Task Attributes
| Attribute | Description | Default | Required |
|---|---|---|---|
| name | The name of the property to set. | None | Yes, unless 'file' is used. |
| value | The value of the property. | "" | No |
| unset | Removes the property from the project as if it had never been set. | false | No |
| file | The name of a standard properties file to load variables from. | None | No |
In the following example, the property x is first set to "6", then evaluated by the if , and reassigned the value "12". The echo task will print out 12.
<var name="x" value="6"/> <if> <equals arg1="${x}" arg2="6" /> <then> <var name="x" value="12"/> </then> </if> <echo>${x}</echo> <!-- will print 12 --> |
The next example shows a property being set, echoed, unset, then reset:
<property name="x" value="6"/> <echo>${x}</echo> <!-- will print 6 --> <var name="x" unset="true"/> <property name="x" value="12"/> <echo>${x}</echo> <!-- will print 12 --> |
The following shows some more uses of the Variable task. It is especially handy for property appending. Notice a couple of things: the property task can't override a var value, in general, you should use var with the unset attribute to change the value of a property.
<var name="x" value="6"/> <echo>x = ${x}</echo> <!-- print: 6 --> <var name="x" value="12"/> <echo>x = ${x}</echo> <!-- print: 12 --> <var name="x" value="6 + ${x}"/> <echo>x = ${x}</echo> <!-- print: 6 + 12 --> <var name="str" value="I "/> <var name="str" value="${str} am "/> <var name="str" value="${str} a "/> <var name="str" value="${str} string."/> <echo>${str}</echo> <!-- print: I am a string. --> <var name="x" value="6"/> <echo>x = ${x}</echo> <!-- print: 6 --> <property name="x" value="12"/> <echo>x = ${x}</echo> <!-- print: 6 (property can't override) --> <var name="x" value="blue"/> <tstamp> <format property="x" pattern="EEEE"/> </tstamp> <echo>Today is ${x}.</echo> <!-- print: Today is blue. --> <var name="x" value="" unset="true"/> <tstamp> <format property="x" pattern="EEEE"/> </tstamp> <echo>Today is ${x}.</echo> <!-- print: Today is Friday. --> |
Copyright © 2003-2004 Ant-Contrib Project. All rights Reserved.


After witnessing my managers struggle to create schedules and losing hair over it, I decided to make a free app to do it for you! Scheduely is a WPF Application written in C#. You can easily add or remove employees, and edit their availability. For easy usage, the program will write a file to disk so data will not have to be inputted each time. Once done editing, the user can click on "Create Schedule" and the program will create a schedule that best works for the employees. To see it in action, click here, or to view the source code click here.


Getting Started
An overview of JBot, how to download and use, basic commands and examples, and more.
Please note the bot will not work with the Extension BetterTTV. In the future the bot will be compatible.
Open your Twitch Channel. (Note: Not your profile page)
Correct URL
http://www.twitch.tv/jeopardybot
Be sure to substitute JeopardyBot with your Twitch username.
Incorrect URL
http://www.twitch.tv/jeopardybot/profile
Log into your Twitch Account if you are not already. (Note: The logged in user must be the owner of the channel)
The bot will not run in another streamers channel without their permission.
Refer to the FAQ section to run the bot in another streamers channel.
The FAQ section has not been create yet. Kappa
Send the chat message "!join" without quotes. The bot will indicate that it has joined your chat.
If the bot does not respond to the !join command. Refresh the page. The Extension might not have been initialized in the tab when it was installed.
The !join command has an optional username parameter. This parameter can be used to allow another user running the bot to run their instance of the bot in your chat.
Example: !join @AndrewR74
The bot ran by AndrewR74 will then join your channel.
Note: The person trying to run the bot in your channel must be viewing your channel.
Test the bot functionality by entering the command "!riddle" to generate a random riddle.
It is very important to keep the tab, running the bot, open at all times. Closing the tab will make the bot leave your chat.
To make the bot leave your chat without closing the tab use the command "!jleave"
Bot Settings
Leave blank if you don't plan to run the bot for a long period of time unattended.
Auto Login into your Twitch account when logged out.
Bot Database
Database Modifications
Database Keys
Module Management
Enter channel names that this module can not run in. Otherwise the module will run in all channels.
Module Development
Developer Account
Existing Developer
New Developer
Developer Portal
My Modules
Pending Module Updates/Publishes
Publish Module
Command Documentation
General Commands
- Cool Down: 2 mins
- Access Level: All
- Example: !jbot
- Player Cool Down: 2 minute
- Access Level: All
- (x) Optional: Player name.
- Example (Get your lifetime score.): !jscore
- Example (Get another players score): !jscore @AndrewR74
- Global Cool Down: 2 minutes
- Access Level: All
- (x) Optional: Number of top players to display.
- (y) Optional: Daily or lifetime scores of the top x players.
- Example (Get the player with the highest lifetime score): !Jleader
- Example (Get top 5 lifetime player scores): !Jleader 5
- Example (Get top 5 daily player scores): !Jleader 5 daily
Game Commands
- Cool Down: dynamic
- Access Level: All
- Example: !riddle
- Cool Down: dynamic
- Access Level: All
- Example: !Jeopardy
- Cool Down: dynamic
- Access Level: All
- Example: !trivia
- Cool Down: none
- Access Level: All
- Example: !hint
- Cool Down: none
- Access Level: Broadcaster, Moderator, Administrator
- Example: !skip
| !Javg | Average chat messages over an interval | 1 minute | All | Optional: Number: A positive integer to use as a sample | ||||
| !Jenable | Enables a certain setting of the bot | No Cool Down | Broadcaster, Administrator | Mandatory: String: [ lurkbot, games, chat ] | ||||
| !Jdisable | Disables a certain setting of the bot. | No Cool Down | Broadcaster, Administrator | Mandatory: String: [ lurkbot, games, chat ] | ||||
| !Jtracker | Display tracker statistics. | 2 minutes | All | Optional[0]: String: [reset, add, delete] | Mandatory[0]: String: Word |
(All): !jtracker
(Broadcaster, Administrator): !jtracker reset
(Broadcaster, Administrator): !tracker add Hello
|
||
| !Jset | Change a bot setting value. | No Cool Down | Broadcaster, Administrator | Mandatory: String: [timeout, gtimespan] | Mandatory: String||Number: Value |

Roulette Commands
 Jroulette - Start a game of roulette. Anyone who wants to play has 30 seconds to place bets. Access Level: All bet <BetName> <[Values]> <Amount> - Place a bet Access Level: All Mandatory Parameter 1: [ even, odd, red, black, high, low, number, row, rsplit, column, dozen ] Optional Parameter 2: integer value. (Only for a Number bet) Mandatory Parameter 3: Amount being bet. (Positive integer value) Bet Examples !bet [Even, Odd, Red, Black, High, Low] <BetAmount> !bet number [-1 - 36] <BetAmount> -1 = 00 !bet row [1 - 12] <BetAmount> !bet rsplit [1 - 12] [1 - 12] <BetAmount> Parameter 1: Row Choice 1 Parameter 2: Row Choice 2 Note: Row Choice 2 must be a row next to Row Choice 1 !bet column [1 - 3] <BetAmount> !bet dozen [1 - 3] <BetAmount> Note: The 1st dozen, 2nd dozen, 3rd dozen. JMoney <PlayerName> - Get a players money Access Level: All Optional Parameter 1: Players name. Default value is callers name. JSpin - Spin the wheel ending the timer. Access Level: Broadcaster, Dev, Moderator JMoney <Action> <Player> <Amount> - Modify players money. Access Level: Broadcaster, Dev Parameter 1: [Give, Take, Reset] Parameter 2: The players name that the action will be applied to. Parameter 3: The amount to taken or given to the player. Exclude parameter for Reset action. JSet StartAmount <Amount> - How much money a first time player is given to start playing. JSet BetTimeSpan <Seconds> - How long before the bot waits before automatically spinning. JSet rTimeSpan <Seconds> - How long players must wait after a game ends before another one can start. JSet BustAmount <Amount> - How much money a player that went bankrupt would receive to play again. JSet BustModMultiplier <Multiplier> - How much the Bust Amount would be multiplied by when a channel moderator went bankrupt. JSet BustSubMultiplier <Multiplier> - How much the Bust Amount would be multiplied by when a channel subscriber went bankrupt. JSet ModTimeout <Seconds> - How long a channel moderator has to wait before they can play again after going bankrupt. JSet SubTimeout <Seconds> - How long a channel subscriber has to wait before they can play again after going bankrupt. JSet PlebTimeOut <Seconds> - How long a channel pleb has to wait before they can play again after going bankrupt.

JTeam Commands

How To Run

 All commands must be follow the !JTeam keyword. Note: Team names with spaces must be surrounded with quotation marks. This rule applies to all JTeam commands. Example: !JTeam Create "Bobs Team" General Commands !JTeam <PlayerName> Get the current team of a player. The player name is optional and is defaulted to the callers username. /all List all of the teams on the channel. Team Modifiers Create <TeamName> Create a new team. Delete <TeamName> Delete an existing team. Members <TeamName> List all the members of a team. <TeamName> Get SubMode Get the Sub Mode Only value of a team. <TeamName OR /all> Exec <Command Names> Execute a team command for a particular team or all channel teams. <TeamName> Set SubMode <Boolean> Change the Sub Mode Only value of a team. <TeamName> Set Name <NewTeamName> Change the name of a team. Team Members <TeamName> Member import Import members into a team. Developer Only. <TeamName> Member Create @<PlayerName> Add a new member to the team. Note: A non subscriber member will be removed from the team if the team is in Sub Mode Only. <TeamName> Member Delete @<PlayerName> Delete an member from a team. <TeamName> Member Mod @<PlayerName> Not used. <TeamName> Member UnMod @<PlayerName> Not used. <TeamName> Member AddLeader @<PlayerName> Not used. <TeamName> Member RmvLeader @<PlayerName> Not used. Team Commands <TeamName OR /all> Command Create <Name> "<Command>" Creates a command that can be executed for all team members. The <Name> parameter is used for the execute command. Note: The name can not contain semicolons. If the command contains the members name in the command; the <name> tag can be substituted. The members name will automatically be inserted into the command during execution. <TeamName OR /all> Command Delete <Name> Delete an exising command by it's name.


CollectGenome
This
Executor is a subclass of
SQLUser which collects Genome databases, as
described
under SQLUser. While the whole collection is referred to as a 'genome'
and its subdivisions as 'chromosomes' CollectGenome can be used on
smaller
entities than whole genomes.
CollectGenome has five parameters:
- Generation: The file generation to fetch data from.
Default: 1.
- MinChainScore: Chains with lower score than this are
rejected. Default: 250.
- MinProcessScore: Chains with lower score than this
are not given the full time-consuming treatment. The columns
RepBaseFinds, PolClass and BestRefRV are not filled unless the job is
already done by RetroVID and ORFID (if ClusterMode = Yes). Default:
300.
- MinLTRPairScore: LTR candidate pairs with lower
PairFactor than this and not belonging in a Chain are ignored. Default:
0.
- MultiPuteins: If Yes, more than one Putein of the
same Gene may be associated with the same (multigenus) Chain.
The file generation is contained in the file name. Eg, a file named
002SelectedChains.txt has generation 2.
Below the ordinary contents of a startup parameter window, there are a
number of other controls, whose use is described below.
The procedure for using CollectGenome is as follows:
- In the Choose genome field, specify the name of a new
genome database to create or an old one to extend.
- Click 'Add one row'.
- Use the file dialog
to choose a directory (typically a whole
chromosome, possibly zipped) to collect from. Its path will appear
above Long
comment.
- Enter any text of any length that catches your fancy
in the 'Long comment' field.
- Enter a unique identifier, typically the number of
the chromosome, in 'Chromosome'.
- Click 'Add row'. The data you just specified will
appear as a new row in the chromosome list. If you made an error, it
may be removed with
Delete last row.
- Repeat 2-6 to your heart's content.
- Not necessary, but it may be a good idea to
select-copy-paste the
contents of the chromosome list into a text file. It can then be
reimported with the 'Import' button, which can save some tedious work.
- Click 'Run' and let CollectGenome work - possibly for
days
if you are collecting a full genome. The RetroTector main window will
give an idea of what is going on. If you chose an old database, you
will be asked if you actually want to add to it, and if you want old
data belonging to the relevant chromosomes to be removed first. This is
useful if a run was interrupted in the middle of a chromosome.
The results may be viewed using any suitable SQL viewer, or
Genomeview.
It is also possible (with the 'Import' button) to import a
tab-delimited
text file into the chromosome list. See point 8 above.


Early voting is available right now!
X days left to vote through the mail
November 6th is my favorite date


Get up and running
Using the EventStack Partner API is simple. Everything you need to get up and running is here, and for anything not included here, please email<EMAIL_ADDRESS>Click the button below to sign up for the API Partner program. You'll receive your key via email, and you are ready to begin making calls.
To use the EventStack Partner API, please request a key below. The key will be emailed to you. This key needs to be included in the header of every API request made. Requests without a valid Key included will be returned an HTTP 401 Unauthorized error.
There is a rate limit of 100 Partner API requests per minute. Requests submitted in excess of this will return an HTTP 429 Error "Too Many Requests".
The Events API can be used to retrieve a listing of local events for a metro area, ordered by distance from a specified point.
| lat | The latitude value of the point the desired events should be centered around. The Events API will return up to 100 events in groups of 20 events, sorted by distance. |
| lng | The longitude value of the point the desired events should be centered around. The Events API will return up to 100 events in groups of 20 events, sorted by distance. |
| page | Optional, default 0. Controls the group number of 20 events. For example, page=0 returns events 0-20; page=1 returns events 21-40. |
[Coming soon] The Events POST can be used to add an event to the stack.
Payload:
| body | Description of the event. |
| eventdate | Date of event in ISO format YYYY-MM-DD'T'HH:MI:SS'Z' |
| lat | The latitude value of the point the desired events should be centered around. |
| lng | The longitude value of the point the desired events should be centered around. |
Possible response and error codes:
| 200 | GET request received, response successfully returned. |
| 202 | POST received. |
| 401 | Unauthorized error. Partner key is not valid. |
| 429 | Rate limit error. Rate limit was exceeded. |


This document defines a standard set of data types and data structures, to aid interoperability of peers at the application level of an EPICS V4 network.
The types described here are approximately equivalent to EPICS V3 "DBR types", though Normative Types extend the concept to structured data. Additionally, these types may be used to define pvIOC records, or may be used purely for data exchange though the dynamic data exchange interfaces offered by pvAccess and pvData.
The function of each Normative Types is described, and their type data structures are defined.
For more information about EPICS, please refer to the home page of the Experimental Physics and Industrial Control System.
This is the 2nd March 2012 version of the Normative Types document. This version includes major changes to the type description formalism used, renames a number of Normative Types descriptions, introduces NTVariantArray, and changes the definition of most types. In short, a major revision.
A notable absence from this document is how Normative Types should identify themselves as such. At present, the name of the structure which encapsulates the type conforming to a Normative Type, may be named with the name of the type. For instance, a structure that should be interpreted as a NTTable, should be named "NTTable." But whether this shall be the standard for self-identity is not yet decided.
This version is an editors draft towards the First Public Working Draft. The First Public Working Draft will be intended for the EPICS community to review and comment. Resulting comments will drive subsequent revisions of the Normative Types specification and the EPICS V4 Working Group's reference implementations of software that helps create, populate and exchange Normative Type PVData.
Comments are welcome, though bear in mind this is a pre-public release version.
The terms MUST, MUST NOT, SHOULD, SHOULD NOT, REQUIRED, and MAY when highlighted (through style sheets, and in uppercase in the source) are used in accordance with RFC 2119 [RFC2119]. The term NOT REQUIRED (not defined in RFC 2119) indicates exemption.
The Normative Types described in this document are intended to be a set of well known data types, including structured data types, capable of handling a significant portion of data exchanges common in online scientific instrument operations. Since EPICS V4 makes it possible to exchange an infinite variety of structured data types between EPICS V4 peers, the intention is that by conforming only to Normative Types, a peer can ensure that any Normative Type conforming client will be able to understand the data transmitted to it, and be able to take processing steps appropriate to that data.
The EPICS version 4 module PVData [bib:pvdata] supplies a typing mechanism and object management API for efficiently defining, creating, accessing and updating memory resident structured data. EPICS V4 module PVAccess [bib:pvaccess] supports the efficient exchange of pvData defined data between EPICS V4 network peers. EPICS V4 Normative Types, defines some general purpose data types, that build on the pvData. These are designed to be generally applicable to controls and the application level of scientific instruments.
The simplest example is the Normative Type "NTScalar". When a client receives a pvData datum which identifies itself as being of type NTScalar, the client will know to expect the scalar's value will be accompanied by an indication of alarm severity and a timestamp (see example below).
An example of a simple normative type is the NTScalar:
structure NTScalar time_t timeStamp alarm_t alarm double value
A more complex example; if a client receives a pvData datum which identifies itself as being of type NTTable, this document specifies that it should expect the datum to contain 0 or more arrays of different types. The definition of NTTable below will say that the client should interpret the arrays as the columns of a table, and should render appropriately as a table, with rows being the same numbered elements of each array.
structure NTTable string[] labels // Very short text describing each field below, i.e. column labels {scalar_t[] colname}0+ // 0 or more scalar array type instances, the columns. string descriptor : opt alarm_t alarm : opt time_t timeStamp : opt
A Normative Type can be used both for sending data from client to service and from service to client. In this document we refer generally to an agent, being either a client or a server. If the agent is specifically at the user's end, we call it the user agent. Client and server refer to the directionality of the transaction, server being the agent that is doing the sending.
All the EPICS V4 Normative Types are defined as particular structure instance definitions of a pvData Structure. Put simply, Normative Types are pvData structures, specifically "top level structures" Needs reference, I couldn't find a definition - Marty!. This is true even of the Normative Types describing simple values like a single int, since a given Normative Type defined datum may include alarm or timestamp. Hence, all Normative Types are structures. The fields of a given Ntype then, can be ascertained at runtime by the pvData Field introspection interface bib:pvdata.
Definition: Normative Type
The Normative Types defined in this document each have the following general form:
The Normative Type data descriptions are given with the syntactic conventions and grammar given below. This is a hybrid of the pvData "Meta" Language and BNF, in order to add clear distinctions between symbol types, particularly terminality, recurrence, which names a user is expected to add and which are predefined.
italics - a non-terminal. Used to stand for a choice of pvData type, or named sequence of fields, or for fields that are themselves defined as structures, and hence non-terminal. In implementation the latter will have pvData field Type structure
plaintext - terminals, either a terminal pvData type name or a label. In the case of terminal pvData type, in implementation these will be instances of pvData Field types scalar or scalarArray, eg double or int [].
name - A user provided label name. This is a kind of terminal. A programmer using the Normative Type will choose what goes in the <>.
{ } - a sequence of occurrences of the item or items in the braces. The number of occurrences is given in the following subscript, 0+ means 0 or more, 1+ means 1 or more.
The grammar for a normative type definition follows the pattern below. That is, a Normative Type is defined as a structure composed of fields. A field may be optional, and may be described along with a comment:
structure NTname { ( ntfield fieldName [:opt] [// comment text] ) }1+where:
This section defines the fields that may appear in a Normative Type's definition.
Each field of a normative type ( ntfield_t ) will be one of the following:
ntfield := scalar_t // a simple numerical or string value | scalar_t[] // an array of simple values | enum_t // an enumeration | enum_t[] // an array of enumerations | time_t // a point in time, used for timestamps | time_t[] // an array of points in time | alarm_t // a summary diagnostic of a control system event | alarm_t[] // an array of summary diagnostics | alarmLimit_t // value thresholds for a control system diagnostic report | alarmLimit_t[] // an array of threshold values | display_t // meta data of displayed data | display_t[] // an array of display mata data | control_t // No idea | control_t[] // No idea
Note that of all the Normative Type fields only scalar_t is of simple type, that is, having a single or array value. All the others are represented by a structure (see Structure Normative Fields below).
The field is a scalar value. Scalar fields would be implemented with PVData field Type "scalar":
scalar_t :=
boolean // true or false
| byte // 8 bit signed integer
| short // 16 bit signed integer
| int // 32 bit signed integer
| long // 64 bit signed integer
| float // single precision IEEE 754
| double // double precision IEEE 754
| string // UTF-8 *
The field is an array of scalars. Scalar array fields would be implemented with PVData field Type "scalarArray":
scalar_t[] :=
boolean[] // array of true or false
| byte[] // array of 8 bit signed integer
| short[] // array of 16 bit signed integer
| int[] // array of 32 bit signed integer
| long[] // array of 64 bit signed integer
| float[] // array of single precision IEEE 754
| double[] // array of double precision IEEE 754
| string[] // array of UTF-8 *
This subsection defines those fields of a Normative Type structure definition, that are themselves structures or arrays of structures.
The structured normative fields would be implemented with type PVData field Type "structure" or "structureArray".
An enum_t[] describes an enumeration. The field is a structure describing a value drawn from a given set of valid values also given. It is implemented as a pvData Field of Type "structure" with the following form:
enum_t := structure aname int index string[] choices
where:
In the version of this doc I started from, the structure name of an enum was defined to anyName, but that's not true of the other Ntype fields - they all must be named by their field type. Would have thought unless we invent a system for self id of Ntype fields, an enum field must also self identify by being called an "enum"?
An enum_t[] describes an array of enumerations. The field is an array of structures each describing a value drawn from a given set of valid values also given in each. It is implemented as a PVData field of Type "structureArray" each element of which with the form of enum_t above.
A time_t describes a defined point in time. The field is a structure describing a time relative to midnight on January 1st, 1970 UTC. It is implemented as a pvData field of Type "structure" with the following form:
time_t :=
structure timeStamp
long secsPastEpoch
int nanoseconds
int userTag
where:
pvData provides two helper classes for a timeStamp structure: timeStamp, and PVTimeStamp.
A time_t[] describes an array of points in time. The field is an array of structures each describing a time relative to January 1st, 1970 UTC. It is implemented as a PVData field of Type "structureArray" each element of which with the form of time_t above.
An alarm_t is a What precisely? I have no idea. Marty or someone who can express what an alarm is functionally has to write this. Must include what severity and status actually are. . The field is a structure describing an alarm. It is implemented as a PVData field of Type "structure" with the following form:
alarm_t :=
structure alarm
int severity
int status
string message
where:
pvData provides two helper classes for an alarm structure: alarm, and PVAlarm.
An alarm_t[] is an array of alarm conditions. The field is an array of structures each describing an alarm condition. It is implemented as a PVData field of Type "structureArray" each element of which with the form of alarm_t above.
An alarmLimit_t is a What precisely? I have no idea. Marty or someone who can express what an alarmLimit is functionally has to write this. Must include the exact interpretation of the fields - because the text as it is makes the field look redundant. It is implemented as a PVData field of Type "structure" with the following form:
alarmLimit_t :=
structure alarmLimit
double highAlarm
double highWarning
double lowWarning
double lowAlarm
where:
Where an alarmLimit_t structure instance is present in a Normative Type structure, it MUST be interpreted as referring to that Normative Type's field named "value". Therefore it is only used in Normative Types that have a single numeric "value" field.
An alarmLimit_t[] is an array of alarm limit conditions. The field is an array of structures each describing an alarm limit. It is implemented as a PVData field of Type "structureArray" each element of which with the form of alarmLimit_t above.
A display_t is a What precisely? I have no idea. Marty or someone who can express what a display is functionally has to write this. . The field is a structure describing an alarm condition. It is implemented as a PVData field of Type "structure" with the following form:
display_t :=
structure display
double limitlow
double limithigh
string description
string format
string units
where:
Where an display_t structure instance is present in a Normative Type structure, it MUST be interpreted as referring to that Normative Type's field named "value". Therefore it is only used in Normative Types that have a single numeric "value" field.
A display_t[] is an array of display_t. The field is an array of structures each describing a What precisely?. It is implemented as a PVData field of Type "structureArray" each element of which with the form of display_t above.
An control_t is a What precisely? I have no idea. . It is implemented as a PVData field of Type "structure" with the following form:
control_t :=
structure control
double limitlow
double limithigh
where:
A control_t[] is an array of control_t. The field is an array of structures each describing a What precisely?. It is implemented as a PVData field of Type "structureArray" each element of which with the form of control_t above.
Since a primary reason for Normative Types is to interoperably pass data between EPICS V4 agents, particularly where the receiver may be generic code that takes action on the data alone with no context (think caget), some support for optional meta data are included.
There is no required interpretation of these fields, and therefore their meaning is not further described in the Normative Type definitions below.
An object of Normative Type may optionally include a field named "descriptor" and of type string, to be used to give identity, name, or sense information. For instance, it may be valued with the name of a device associated with control data, or the run number of a table of model data.
string descriptor :opt // Contextual information
An object of Normative Type may optionally include an alarm field.
alarm_t alarm :opt // Control system event summary
An object of Normative Type may optionally include a timeStamp field.
time_t timeStamp :opt // Event time
The General Normative Types are for encapsulating data of any kind of application or use case. Compare to Specific Normative Types defined later in this document, and which are oriented to particular use cases.
NTScalar is an EPICS V4 Normative Type that describes a single scalar value plus metadata:
structure NTScalar scalar_t value string descriptor :opt time_t timeStamp :opt alarm_t alarm :opt display_t display :opt control_t control :opt
where:
NTEnum is an EPICS V4 Normative Type that describes an enumeration (a closed set of possible values each described by an n-tuple).
structure NTEnum enum_t value string descriptor :opt time_t timeStamp :opt alarm_t alarm :opt
where:
NTMatrix is an EPICS V4 Normative Type used to define an N-dimensional matrix of some numeric scalar type.
structure NTMatrix
(boolean [] | byte[] | short[] | int[] | long[] | float[] | double[]) value
int[] dim :opt
string descriptor :opt
time_t timeStamp :opt
alarm_t alarm :opt
display_t display :opt
where:
User agents that print or otherwise render an NTMarix SHOULD print row vector, column vector, and non-vector matrices appropriately.
Do we need a specification of the memory layout of the value field?
Such a spec would only be useful if we enable programmers to manipulate references to
the in memory data (which is I think the point of pvData), so I would guess yes. In
that case, do we have to say value
MUST be laid out in memory in
row-major order (ie C like) or column-major (Fortran, Matlab). Answer to this depends
on whether Ntypes may be conformantly used other than in interoperations (ie, for
processing too). If the normative spec says that it covers only interop, then it has
no business telling a user how to represent their data prior to packaging. But if an
instance of an NTMatrix defined structure may be used in processing, then its in
memory layout must be predictable.
NTVariantArray is an EPICS V4 Normative Type to define a single structure which contains an number of arrays, each of different type, but where the value of the NTVariantArray as a whole is taken to be the value of only one of the arrays at a time. In that way, it can be used to encode data in arrays whose type may be changed according to runtime conditions and the data to be expressed.
NTVariantArray is defined with arrays of each pvData scalar type. At any
particular time its value MUST be interpreted to be only one of these arrays. The
dataType
member specifies which array MUST be taken to be the
NTVariantArray's type. The data arrays need not be all the same length. Arrays other
than that presently selected by dataType
MAY be populated; in this way
dataType
can be used as a value selector.
structure NTVariantArray int dataType // Identifies which scalar array defines the present value boolean [] booleanValue // Defines the NTVariantArray's value if dataType == 0 byte [] byteValue // Defines the NTVariantArray's value if dataType == 1 short [] shortValue // Defines the NTVariantArray's value if dataType == 2 int [] intValue // Defines the NTVariantArray's value if dataType == 3 long [] longValue // Defines the NTVariantArray's value if dataType == 4 float [] floatValue // Defines the NTVariantArray's value if dataType == 5 double [] doubleValue // Defines the NTVariantArray's value if dataType == 6 string [] stringValue // Defines the NTVariantArray's value if dataType == 7 timestamp_t[] timeStampValue // Defines the NTVariantArray's value if dataType == 8 alarm_t [] alarmValue // Defines the NTVariantArray's value if dataType == 9 string descriptor :opt time_t timeStamp :opt alarm_t alarm :opt display_t display :opt
where:
0 - booleanValue 1 - byteValue 2 - shortValue 3 - intValue 4 - longValue 5 - floatValue 6 - doubleValue 7 - stringValue 8 - timeStampValue 9 - alarmValue
Note that NTVariantArray is the only Ntype that does not have a field named "value", and therefore marks an exception to a rule that would otherwise be useful for trivial Ntype deserializers. Should we change "dataType" to be named "value"?
The "specific normative types" below are types oriented towards application level scientific and engineering use cases. Compare to General Normative Types defined above. The currently defined types are each described in a section below.
Unless otherwise stated:
NTNameValue is an EPICS V4 Normative Type that describes a single name (or "key") string and associated array of scalar value.
Where the datum to be expressed is just a single scalar, the value array would simply have a length of one. Since one NTNameValue expresses a single name and value, it is expected that arrays of NTNameValue objects would commonly be used. For the related problem of expressing two congruent arrays, one of keys and one of scalar values, see NTTable.
Use cases: In a school, a single NTNamedValue might describe one grade for one student; an array of NTNamedVales of scalar type would describe the grades for each student in a class. In a particle accelerator, an array of NTNamedValues could summarise all of the important properties of a control system device, by name and (possibly array) value.
structure NTNameValue string name scalar_t[] value string descriptor :opt time_t timeStamp :opt alarm_t alarm :opt
where:
MultichannelArray is an EPICS V4 Normative Type that aggregates an array of scalar values from different EPICS Process Variable (PV) channel sources, into a single variable.
Use cases; in a particle accelerator, a single NTMultichannelArray might include the data of a number of Beam Positon Monitors' X offset values, or of a number of quadrupoles' desired field values.
structure NTMultichannelArray scalar_t[] value // The channel values string[] PVnames // Process Variable names time_t timeStamp // Base value time stamp int[] severities :opt // Alarm severity associated with each value double[] positions :opt // The position of each value element double[] deltaTimes :opt // The time relative to the timeStamp, in seconds string descriptor :opt alarm_t alarm :opt
where:
The above descriptions of the optional fields, pertain in particular to when a NTMultichannelArray expresses measured values, but a NTMultichannelArray can be used to express desired values or setpoint values too.
NTTimeDomainArray is an EPICS V4 Normative Type that expresses an array of values from a single signal, where there has been a constant time between each sample; for instance from a PV that has been sampled at a given single frequency.
The data in a NTTimeDomainArray show how the associated signal changes over time. Should the name of the PV be included?
Need use cases. Also, is this definition realistic? Seems to me you'd also want to have an indication of the sampling time error. That is, if the deltaTime was .5, that would be an ideal, and you'd want also to record what was an estimate of when the corresponding sample was really taken, with reference to that notional deltaTime. Need an expert.
structure NTTimeDomainArray
(boolean [] | byte[] | short[] | int[] | long[] | float[] | double[]) value
double deltaTime // Time in seconds between each sample
string descriptor :opt
alarm_t alarm :opt
time_t timeStamp :opt
where:
Need to include units?
NTFrequencyDomainArray is the EPICS V4 Normative Type for expressing the values of a signal with respect to frequency.
Needs an expert to check this. Our proto from PSI meeting defined two numbers firstFrequency and deltaFrequency as a single numbers, but surely they must be an array of frequencies? Changed it to array, with 0 index being base freq. Maybe harmonics should be given as deltas to the base. So we need to be more specific about whether harmonics' frequencies are absolute or relative to frequencies[0].
structure NTFrequencyDomainArray
(boolean [] | byte[] | short[] | int[] | long[] | float[] | double[]) value
double[] frequencies // frequencies[0] = base, [>0] = harmonics
string descriptor :opt
alarm_t alarm :opt
time_t timeStamp :opt
where:
Need to include units?
NTHistogram is the EPICS V4 Normative Type used to encode the data and representation of a (1 dimensional) histogram. Specifically, it encapsulates frequency binned data.
For 2d histograms (i.e. both x and y observations are binned) and n-tuple data (e.g. land masses of different listed countries) see NTMatrix or NTTable.
structure NTHistogram
double [] ranges // The start and end points of each bin
long [] counts // The frequency count, or value of each bin
string descriptor :opt
alarm_t alarm :opt
time_t timeStamp :opt
One NTHistogram gives the information required to convey a histogram representation of some underlying observations. It does not convey the values of each of the observations themselves.
The number of bins is given by the length of the counts array. ranges indicates the low value and high value of each bin. The range for bin(i) is given by range(i) to range(i+1). Specifically, since we want end points of both the first bin and last bin included, all bin intervals except the last one, MUST be right half open; from that bin's low value range(i) (included) to that bin's high value range(i+1) (excluded). The last bin MUST be fully open (low and high value included).
A log plot histogram (in which the independent variable x is binned on a log scale), would be communicated using a range array of decades (1.0E01, 1.0E02, 1.0E03 etc).
The array length of range
MUST be the array length of counts + 1.
NTAggregate is the EPICS V4 Normative Type to compactly convey data which combines, several measurements, or observations. An NTAggregate would give a simple summary statistic bib:agg about the central tendency and dispersion of a set of data points.
Use cases: for instance, an NTAggreagte could be used to summarize the value of one beam position offset reading over some number of pulses (N). It also includes the time range of the sampled points, so it could be used for time domain rebasing. For instance, an FPGA sending data at 10KHz, and you want to display its output, but you don't want to display at the native rate. Also, it could be used for transmitting or storing compressed archive data.
NTAggregate doesn't cover the shape of a distribution so it only reasonably helps you do symmetrical distributions (no skewness or kurtosis), and it doesn't include any help for indicating the extent of dependency on another variable (correlation).
structure NTAggregate double mean // Average value of observations double sd // Standard Deviation of observations, or RMS about the mean long N // Number of observations double first opt // Initial observation value time_t firstTimeStamp opt // Time of initial observation double last opt // Final observation value time_t lastTimeStamp opt // Time of final observation double max opt // Highest value in the N observations double min opt // Lowest value in the N observations string descriptor opt alarm_t alarm opt time_t timeStamp opt
Where:
One NTAggregate instance describes some number (given by N) of observations. If firstTimeStamp and lastTimeStamp are given, then the N observations MUST have been taken over the period of time specified. If first, last, max or min are given, they MUST refer to the actual values of the N observations being summarized.
The mean
field value computed by server agents SHOULD be the
arithmetic mean of the observation data being summarized by this NTAggregate.
Which estimator of the standard deviation [1/N or 1/(N-1)] is to be used by
service agents to compute the value of the sd
field, is not defined.
NTImage is the EPICS V4 Normative Type to express image data, particularly camera images. One NTImage gives one frame.
The EPICS V3 image type is provided by areaDetector. See the NDArray class declaration for details of the image properties. The EPICS V4 image type (NTImage) is a superset of this functionality.
Byte [] data may contain a
compressed image so the size may not be at least prod(dim) *
element_size(datatype)
.
An NTImage is composed of three parts:
structure NTImage Arraypart Imagepart Metadatapart
Each of these will be discussed separately.
The Arraypart of an NTImage is composed of the following fields:
(boolean [] | byte[] | short[] | int[] | long[] | float[] | double[]) value
int[] dim
string descriptor :opt
time_t timeStamp :opt
alarm_t alarm :opt
display_t display :opt
These fields are the same as for NTMatrix defined previously.
A generic tool that operates on NTMatrixs will be able to use the image as long as compression is not used.
The Imagepart of an NTImage is composed of the following fields:
int colorMode int bayerPattern char [4] fourcc int [] offset // same length as dim, start of readout int [] binning int [] reverse int [] fullDim
where:
NDColorModeMono = 0, /** Monochromatic image */ NDColorModeBayer = 1, /** Bayer pattern image, 1 value per pixel but with color filter on detector */ NDColorModeRGB1 = 2, /** RGB image with pixel color interleave, data array is [3, NX, NY] */ NDColorModeRGB2 = 3, /** RGB image with row color interleave, data array is [NX, 3, NY] */ NDColorModeRGB3 = 4, /** RGB image with plane color interleave, data array is [NX, NY, 3] */ NDColorModeYUV444 = 5, /** YUV image, 3 bytes encodes 1 RGB pixel */ NDColorModeYUV422 = 6, /** YUV image, 4 bytes encodes 2 RGB pixel */ NDColorModeYUV411 = 7 /** YUV image, 6 bytes encodes 4 RGB pixels */
NDBayerRGGB = 0, /** First line RGRG, second line GBGB... */ NDBayerGBRG = 1, /** First line GBGB, second line RGRG... */ NDBayerGRBG = 2, /** First line GRGR, second line BGBG... */ NDBayerBGGR = 3 /** First line BGBG, second line GRGR... */
The Metadatapart of an NTImage is composed of the following fields:
int uniqueId string [] attributeDescriptions int [] attributeSourceTypes string [] attributeSources NTVariantArray [] attributes
where:
NDAttrSourceDriver = 0, /** Attribute is obtained directly from driver */ NDAttrSourceParam, /** Attribute is obtained from parameter library */ NDAttrSourceEPICSPV /** Attribute is obtained from an EPICS PV */
NTTable is the EPICS V4 Normative Type for "2-d" tabular datasets.
An NTTable is made up of a number of arrays, each array being of a scalar type. Each array can be thought of as a column. Each ith array member makes up one row, or n-tuple.
Use case examples: a table of twiss paramaters of all lattice elements in an accelerator section. Another example, where the columns might vary call-to-call would be that of an EPICS V4 SQL database service. In that example one NTTable returned by the service would contain all the tabular results of a SQL SELECT, essentially a recoded JDBC or ODBC ResultSet - see the rdbService.
structure NTTable string[] labels // Very short text describing each field below, i.e. column labels {scalar_t[] colname}0+ // 0 or more scalar array type instances, the columns. string descriptor : opt alarm_t alarm : opt time_t timeStamp : opt
where:
This represents a table. The number of "columns" is equal to the number of fields which follows field "labels." Each colname[] field has the data for its "column." The value of each element of labels SHOULD be used as a column heading for the corresponding colname field.
Note that the above description is given in terms of a table and its columns, but there is nothing specifically columnar about how this data may be rendered. A user may choose to print the fields row wise. For instance, if there are many fields, but each has only length 1 or 2. E.g., if you wanted to give all the scalar data related to one device, then you might use an NTTable rendered in such a way. Note that one column of a table would also be easily described by NTNameValue.
The number of scalar_t fields and the length of labels MUST be the same. All scalar_t fields MUST have the same length, being the number of "rows" in the table.
Users and developers using EPICS V4 are free to define their own special purpose types on top of PVStructure (or the other PV Types) but should note that only the Normative Types defined here (NT*) above, are intended to be understood by all general purpose EPICS V4 services and clients.


Traditional beef or lamb stew
This is a recipe for a typical Irish stew. This is traditionally made with lamb since it’s cheaper however, beef tastes a lot better and is more readily available in North America I’ve been told. This is good if you want to feed a family or if you just want to be lazy and eat the same thing for 2 or 3 days.
Serve with mashed potatoes.
Ingredients
- Lamb shoulder or beef chuck
- Onion, celery, carrot and garlic
- Thyme, rosemary and some bay leaves.
- Beef or chicken stock
- (Optional) a bottle of stout or porter for some extra flavour.
Directions
- Cut up the onion, carrot and celery into bite-sized chunks roughly the same size as the meat. The garlic can go in whole.
- Brown the meat on all sides.  Do this in batches and try not to overcrowd the pot. Browning the meat on the outside will give it a much nicer texture when you go to eat this and should not be skipped for convenience.
- Remove the meat and add in the vegetables. Adding some salt will help remove the moisture in the veg and will help deglaze the caramelised bits at the bottom of the pot.
- (Optional) If you have a Guinness or some other stout add the meat back in an deglaze with about a third of the can. This will add some extra flavour. Wait until the alcohol has completely evaporated until you stir or continue.
- Add back in the meat and add in the stock and herbs. Lower the heat and allow to simmer for about 2 - 2.5 hours.
- After 2 hours the stew will be a bit thicker but probably still watery. The easiest thing to do is add some cut up potatoes for the last half hour. The starch will help thicken the stew considerably. Otherwise you can mix a teaspoon of flour with water in a cup and slowly add this to the stew while whisking.
There you have it, an idiot-proof stew that should taste reasonably well. Besides browning the meat this is really just throwing stuff into a pot in a certain order. This is the kind of dish that tastes better the next day so it’s ideal for making on a Sunday and eating for the next 2 or 3 days.
Contribution
Recipe tags:
irish
stew
lamb
beef


| 1 |
//
|
|
| 2 |
// RouteComposer
|
|
| 3 |
// DefaultRouter+Extension.swift
|
|
| 4 |
// https://github.com/ekazaev/route-composer
|
|
| 5 |
//
|
|
| 6 |
// Created by Eugene Kazaev in 2018-2022.
|
|
| 7 |
// Distributed under the MIT license.
|
|
| 8 |
//
|
|
| 9 |
// Become a sponsor:
|
|
| 10 |
// https://github.com/sponsors/ekazaev
|
|
| 11 |
//
|
|
| 12 |
|
|
| 13 |
import Foundation
|
|
| 14 |
import UIKit
|
|
| 15 |
|
|
| 16 |
extension DefaultRouter {
|
|
| 17 |
|
|
| 18 |
struct InterceptorRunner {
|
|
| 19 |
|
|
| 20 |
private var interceptors: [(interceptor: AnyRoutingInterceptor, context: AnyContext)]
|
|
| 21 |
|
|
| 22 |
init(interceptors: [AnyRoutingInterceptor], with context: AnyContext) throws {
|
217x |
| 23 |
self.interceptors = try interceptors.map {
|
302x |
| 24 |
var interceptor = $0
|
302x |
| 25 |
try interceptor.prepare(with: context)
|
302x |
| 26 |
return (interceptor: interceptor, context: context)
|
302x |
| 27 |
}
|
302x |
| 28 |
}
|
217x |
| 29 |
|
|
| 30 |
mutating func add(_ interceptor: AnyRoutingInterceptor, with context: AnyContext) throws {
|
27x |
| 31 |
var interceptor = interceptor
|
27x |
| 32 |
try interceptor.prepare(with: context)
|
27x |
| 33 |
interceptors.append((interceptor: interceptor, context: context))
|
27x |
| 34 |
}
|
27x |
| 35 |
|
|
| 36 |
func perform(completion: @escaping (_: RoutingResult) -> Void) {
|
205x |
| 37 |
guard !interceptors.isEmpty else {
|
205x |
| 38 |
completion(.success)
|
5x |
| 39 |
return
|
5x |
| 40 |
}
|
200x |
| 41 |
|
200x |
| 42 |
var interceptors = interceptors
|
200x |
| 43 |
|
200x |
| 44 |
func runInterceptor(interceptor: (interceptor: AnyRoutingInterceptor, context: AnyContext)) {
|
325x |
| 45 |
interceptor.interceptor.perform(with: interceptor.context) { result in
|
325x |
| 46 |
if case .failure = result {
|
325x |
| 47 |
completion(result)
|
1x |
| 48 |
} else if interceptors.isEmpty {
|
325x |
| 49 |
completion(result)
|
199x |
| 50 |
} else {
|
325x |
| 51 |
runInterceptor(interceptor: interceptors.removeFirst())
|
126x |
| 52 |
}
|
325x |
| 53 |
}
|
325x |
| 54 |
}
|
325x |
| 55 |
|
200x |
| 56 |
runInterceptor(interceptor: interceptors.removeFirst())
|
200x |
| 57 |
}
|
200x |
| 58 |
|
|
| 59 |
}
|
|
| 60 |
|
|
| 61 |
struct ContextTaskRunner {
|
|
| 62 |
|
|
| 63 |
var contextTasks: [AnyContextTask]
|
|
| 64 |
|
|
| 65 |
init(contextTasks: [AnyContextTask], with context: AnyContext) throws {
|
117x |
| 66 |
self.contextTasks = try contextTasks.map {
|
117x |
| 67 |
var contextTask = $0
|
2x |
| 68 |
try contextTask.prepare(with: context)
|
2x |
| 69 |
return contextTask
|
2x |
| 70 |
}
|
2x |
| 71 |
}
|
117x |
| 72 |
|
|
| 73 |
mutating func add(_ contextTask: AnyContextTask, with context: AnyContext) throws {
|
106x |
| 74 |
var contextTask = contextTask
|
106x |
| 75 |
try contextTask.prepare(with: context)
|
106x |
| 76 |
contextTasks.append(contextTask)
|
106x |
| 77 |
}
|
106x |
| 78 |
|
|
| 79 |
func perform(on viewController: UIViewController, with context: AnyContext) throws {
|
236x |
| 80 |
try contextTasks.forEach {
|
236x |
| 81 |
try $0.perform(on: viewController, with: context)
|
107x |
| 82 |
}
|
107x |
| 83 |
}
|
236x |
| 84 |
|
|
| 85 |
}
|
|
| 86 |
|
|
| 87 |
struct PostTaskRunner {
|
|
| 88 |
|
|
| 89 |
var postTasks: [AnyPostRoutingTask]
|
|
| 90 |
|
|
| 91 |
let postponedRunner: PostponedTaskRunner
|
|
| 92 |
|
|
| 93 |
init(postTasks: [AnyPostRoutingTask], postponedRunner: PostponedTaskRunner) {
|
117x |
| 94 |
self.postTasks = postTasks
|
117x |
| 95 |
self.postponedRunner = postponedRunner
|
117x |
| 96 |
}
|
117x |
| 97 |
|
|
| 98 |
mutating func add(_ postTask: AnyPostRoutingTask) throws {
|
13x |
| 99 |
postTasks.append(postTask)
|
13x |
| 100 |
}
|
13x |
| 101 |
|
|
| 102 |
func perform(on viewController: UIViewController, with context: AnyContext) throws {
|
236x |
| 103 |
postponedRunner.add(postTasks: postTasks, to: viewController, context: context)
|
236x |
| 104 |
}
|
236x |
| 105 |
|
|
| 106 |
func commit() throws {
|
101x |
| 107 |
try postponedRunner.perform()
|
101x |
| 108 |
}
|
101x |
| 109 |
|
|
| 110 |
}
|
|
| 111 |
|
|
| 112 |
struct StepTaskTaskRunner {
|
|
| 113 |
|
|
| 114 |
private let contextTaskRunner: ContextTaskRunner
|
|
| 115 |
|
|
| 116 |
private let postTaskRunner: PostTaskRunner
|
|
| 117 |
|
|
| 118 |
private let context: AnyContext
|
|
| 119 |
|
|
| 120 |
init(contextTaskRunner: ContextTaskRunner, postTaskRunner: PostTaskRunner, context: AnyContext) {
|
269x |
| 121 |
self.contextTaskRunner = contextTaskRunner
|
269x |
| 122 |
self.postTaskRunner = postTaskRunner
|
269x |
| 123 |
self.context = context
|
269x |
| 124 |
}
|
269x |
| 125 |
|
|
| 126 |
func perform(on viewController: UIViewController) throws {
|
236x |
| 127 |
try contextTaskRunner.perform(on: viewController, with: context)
|
236x |
| 128 |
try postTaskRunner.perform(on: viewController, with: context)
|
236x |
| 129 |
}
|
236x |
| 130 |
|
|
| 131 |
}
|
|
| 132 |
|
|
| 133 |
final class PostponedTaskRunner {
|
|
| 134 |
|
|
| 135 |
private struct PostTaskSlip {
|
|
| 136 |
// This reference is weak because even though this view controller was created by a fabric but then some other
|
|
| 137 |
// view controller in the chain can have an action that will actually remove this view controller from the
|
|
| 138 |
// stack. We do not want to keep a strong reference to it and prevent it from deallocation. Potentially it's
|
|
| 139 |
// a very rare issue but must be kept in mind.
|
|
| 140 |
weak var viewController: UIViewController?
|
|
| 141 |
|
|
| 142 |
let postTask: AnyPostRoutingTask
|
|
| 143 |
}
|
|
| 144 |
|
|
| 145 |
// this class is just a placeholder. Router needs at least one post routing task per view controller to
|
|
| 146 |
// store a reference there.
|
|
| 147 |
private struct EmptyPostTask: AnyPostRoutingTask {
|
|
| 148 |
|
|
| 149 |
func perform(on viewController: UIViewController, with context: AnyContext, routingStack: [UIViewController]) {}
|
210x |
| 150 |
|
|
| 151 |
}
|
|
| 152 |
|
|
| 153 |
private final var taskSlips: [(postTaskSlip: PostTaskSlip, context: AnyContext)] = []
|
118x |
| 154 |
|
|
| 155 |
final func add(postTasks: [AnyPostRoutingTask], to viewController: UIViewController, context: AnyContext) {
|
238x |
| 156 |
guard !postTasks.isEmpty else {
|
238x |
| 157 |
let postTaskSlip = PostTaskSlip(viewController: viewController, postTask: EmptyPostTask())
|
219x |
| 158 |
taskSlips.append((postTaskSlip: postTaskSlip, context: context))
|
219x |
| 159 |
return
|
219x |
| 160 |
}
|
219x |
| 161 |
|
19x |
| 162 |
postTasks.forEach {
|
21x |
| 163 |
let postTaskSlip = PostTaskSlip(viewController: viewController, postTask: $0)
|
21x |
| 164 |
taskSlips.append((postTaskSlip: postTaskSlip, context: context))
|
21x |
| 165 |
}
|
21x |
| 166 |
}
|
19x |
| 167 |
|
|
| 168 |
final func perform() throws {
|
103x |
| 169 |
var viewControllers: [UIViewController] = []
|
103x |
| 170 |
taskSlips.forEach {
|
232x |
| 171 |
guard let viewController = $0.postTaskSlip.viewController, !viewControllers.contains(viewController) else {
|
232x |
| 172 |
return
|
7x |
| 173 |
}
|
225x |
| 174 |
viewControllers.append(viewController)
|
225x |
| 175 |
}
|
225x |
| 176 |
|
103x |
| 177 |
try taskSlips.forEach { slip in
|
232x |
| 178 |
guard let viewController = slip.postTaskSlip.viewController else {
|
232x |
| 179 |
return
|
! |
| 180 |
}
|
232x |
| 181 |
try slip.postTaskSlip.postTask.perform(on: viewController, with: slip.context, routingStack: viewControllers)
|
232x |
| 182 |
}
|
232x |
| 183 |
}
|
103x |
| 184 |
}
|
|
| 185 |
|
|
| 186 |
final class GlobalTaskRunner {
|
|
| 187 |
|
|
| 188 |
private final var interceptorRunner: InterceptorRunner
|
|
| 189 |
|
|
| 190 |
private final let contextTaskRunner: ContextTaskRunner
|
|
| 191 |
|
|
| 192 |
private final let postTaskRunner: PostTaskRunner
|
|
| 193 |
|
|
| 194 |
init(interceptorRunner: InterceptorRunner, contextTaskRunner: ContextTaskRunner, postTaskRunner: PostTaskRunner) {
|
117x |
| 195 |
self.interceptorRunner = interceptorRunner
|
117x |
| 196 |
self.contextTaskRunner = contextTaskRunner
|
117x |
| 197 |
self.postTaskRunner = postTaskRunner
|
117x |
| 198 |
}
|
117x |
| 199 |
|
|
| 200 |
final func taskRunner(for step: PerformableStep?, with context: AnyContext) throws -> StepTaskTaskRunner {
|
270x |
| 201 |
guard let interceptableStep = step as? InterceptableStep else {
|
270x |
| 202 |
return StepTaskTaskRunner(contextTaskRunner: self.contextTaskRunner, postTaskRunner: self.postTaskRunner, context: context)
|
76x |
| 203 |
}
|
194x |
| 204 |
var contextTaskRunner = contextTaskRunner
|
194x |
| 205 |
var postTaskRunner = postTaskRunner
|
194x |
| 206 |
if let interceptor = interceptableStep.interceptor {
|
194x |
| 207 |
try interceptorRunner.add(interceptor, with: context)
|
27x |
| 208 |
}
|
194x |
| 209 |
if let contextTask = interceptableStep.contextTask {
|
194x |
| 210 |
try contextTaskRunner.add(contextTask, with: context)
|
106x |
| 211 |
}
|
194x |
| 212 |
if let postTask = interceptableStep.postTask {
|
194x |
| 213 |
try postTaskRunner.add(postTask)
|
13x |
| 214 |
}
|
194x |
| 215 |
return StepTaskTaskRunner(contextTaskRunner: contextTaskRunner, postTaskRunner: postTaskRunner, context: context)
|
194x |
| 216 |
}
|
194x |
| 217 |
|
|
| 218 |
final func performInterceptors(completion: @escaping (_: RoutingResult) -> Void) {
|
105x |
| 219 |
interceptorRunner.perform(completion: completion)
|
105x |
| 220 |
}
|
105x |
| 221 |
|
|
| 222 |
final func performPostTasks() throws {
|
101x |
| 223 |
try postTaskRunner.commit()
|
101x |
| 224 |
}
|
101x |
| 225 |
|
|
| 226 |
}
|
|
| 227 |
|
|
| 228 |
/// Each post action needs to know a view controller is should be applied to.
|
|
| 229 |
/// This decorator adds functionality of storing `UIViewController`s created by the `Factory` and frees
|
|
| 230 |
/// custom factories implementations from dealing with it. Mostly it is important for ContainerFactories
|
|
| 231 |
/// which create merged view controllers without `Router`'s help.
|
|
| 232 |
struct FactoryDecorator: AnyFactory, CustomStringConvertible {
|
|
| 233 |
|
|
| 234 |
private var factory: AnyFactory
|
|
| 235 |
|
|
| 236 |
private let stepTaskRunner: StepTaskTaskRunner
|
|
| 237 |
|
|
| 238 |
let action: AnyAction
|
|
| 239 |
|
|
| 240 |
init(factory: AnyFactory, stepTaskRunner: StepTaskTaskRunner) {
|
134x |
| 241 |
self.factory = factory
|
134x |
| 242 |
self.action = factory.action
|
134x |
| 243 |
self.stepTaskRunner = stepTaskRunner
|
134x |
| 244 |
}
|
134x |
| 245 |
|
|
| 246 |
mutating func prepare(with context: AnyContext) throws {
|
134x |
| 247 |
try factory.prepare(with: context)
|
134x |
| 248 |
}
|
134x |
| 249 |
|
|
| 250 |
func build(with context: AnyContext) throws -> UIViewController {
|
128x |
| 251 |
let viewController = try factory.build(with: context)
|
128x |
| 252 |
try stepTaskRunner.perform(on: viewController)
|
128x |
| 253 |
return viewController
|
128x |
| 254 |
}
|
128x |
| 255 |
|
|
| 256 |
mutating func scrapeChildren(from factories: [(factory: AnyFactory, context: AnyContext)]) throws -> [(factory: AnyFactory, context: AnyContext)] {
|
134x |
| 257 |
try factory.scrapeChildren(from: factories)
|
134x |
| 258 |
}
|
134x |
| 259 |
|
|
| 260 |
var description: String {
|
96x |
| 261 |
String(describing: factory)
|
96x |
| 262 |
}
|
96x |
| 263 |
|
|
| 264 |
}
|
|
| 265 |
|
|
| 266 |
final class DefaultPostponedIntegrationHandler: PostponedActionIntegrationHandler, MainThreadChecking {
|
|
| 267 |
|
|
| 268 |
private(set) final var containerViewController: ContainerViewController?
|
|
| 269 |
|
|
| 270 |
private(set) final var postponedViewControllers: [UIViewController] = []
|
105x |
| 271 |
|
|
| 272 |
final let logger: Logger?
|
|
| 273 |
|
|
| 274 |
final let containerAdapterLocator: ContainerAdapterLocator
|
|
| 275 |
|
|
| 276 |
init(logger: Logger?, containerAdapterLocator: ContainerAdapterLocator) {
|
105x |
| 277 |
self.logger = logger
|
105x |
| 278 |
self.containerAdapterLocator = containerAdapterLocator
|
105x |
| 279 |
}
|
105x |
| 280 |
|
|
| 281 |
final func update(containerViewController: ContainerViewController, animated: Bool, completion: @escaping (_: RoutingResult) -> Void) {
|
2x |
| 282 |
do {
|
2x |
| 283 |
guard self.containerViewController == nil else {
|
2x |
| 284 |
purge(animated: animated, completion: { result in
|
! |
| 285 |
self.assertIfNotMainThread()
|
! |
| 286 |
guard result.isSuccessful else {
|
! |
| 287 |
completion(result)
|
! |
| 288 |
return
|
! |
| 289 |
}
|
! |
| 290 |
self.update(containerViewController: containerViewController, animated: animated, completion: completion)
|
! |
| 291 |
})
|
! |
| 292 |
return
|
! |
| 293 |
}
|
2x |
| 294 |
self.containerViewController = containerViewController
|
2x |
| 295 |
postponedViewControllers = try containerAdapterLocator.getAdapter(for: containerViewController).containedViewControllers
|
2x |
| 296 |
logger?.log(.info("Container \(String(describing: containerViewController)) will be used for the postponed integration."))
|
2x |
| 297 |
completion(.success)
|
2x |
| 298 |
} catch {
|
2x |
| 299 |
completion(.failure(error))
|
! |
| 300 |
}
|
2x |
| 301 |
}
|
2x |
| 302 |
|
|
| 303 |
final func update(postponedViewControllers: [UIViewController]) {
|
3x |
| 304 |
self.postponedViewControllers = postponedViewControllers
|
3x |
| 305 |
}
|
3x |
| 306 |
|
|
| 307 |
final func purge(animated: Bool, completion: @escaping (_: RoutingResult) -> Void) {
|
198x |
| 308 |
do {
|
198x |
| 309 |
guard let containerViewController else {
|
198x |
| 310 |
completion(.success)
|
196x |
| 311 |
return
|
196x |
| 312 |
}
|
196x |
| 313 |
|
2x |
| 314 |
let containerAdapter = try containerAdapterLocator.getAdapter(for: containerViewController)
|
2x |
| 315 |
|
2x |
| 316 |
guard !postponedViewControllers.isEqual(to: containerAdapter.containedViewControllers) else {
|
2x |
| 317 |
reset()
|
! |
| 318 |
completion(.success)
|
! |
| 319 |
return
|
! |
| 320 |
}
|
2x |
| 321 |
|
2x |
| 322 |
containerAdapter.setContainedViewControllers(postponedViewControllers,
|
2x |
| 323 |
animated: animated,
|
2x |
| 324 |
completion: { result in
|
2x |
| 325 |
guard result.isSuccessful else {
|
2x |
| 326 |
completion(result)
|
! |
| 327 |
return
|
! |
| 328 |
}
|
2x |
| 329 |
self.logger?.log(.info("View controllers \(String(describing: self.postponedViewControllers)) were simultaneously "
|
2x |
| 330 |
+ "integrated into \(String(describing: containerViewController))"))
|
2x |
| 331 |
self.reset()
|
2x |
| 332 |
completion(.success)
|
2x |
| 333 |
})
|
2x |
| 334 |
} catch {
|
2x |
| 335 |
completion(.failure(error))
|
! |
| 336 |
}
|
2x |
| 337 |
}
|
2x |
| 338 |
|
|
| 339 |
private final func reset() {
|
2x |
| 340 |
containerViewController = nil
|
2x |
| 341 |
postponedViewControllers = []
|
2x |
| 342 |
}
|
2x |
| 343 |
|
|
| 344 |
}
|
|
| 345 |
|
|
| 346 |
}
|
|


You can change the colors in the pattern to suit your yarn by clicking on the color fields. If you want to reduce the amount of colors in the pattern, you can select any color and merge it with other colors. You can change individual stichtes in the pattern by clicking on them to cycle through the colors.
{{ #save }} {{ /save }} {{ #saved }}Pattern saved as: {{ name }}
{{ /saved }}Select


Two pi constants convenient for computation.
Returns the value itself if it's between min and max. Returns min if the value is lower than min. Returns max if the value is greater than max.
the value to clmap
the min value to clamp to (default: 0)
the max value to clamp to (default: 1)
the clamped value
Calculates the shortest difference between two given angles given in degrees.
current angle in degrees
target angle in degrees
the delta
Denormalize the value from 0.0 and 1.0 using min and max values
value to denormalize
max to denormalize between
min to denormalize between
the denormalized value
Returns a new scalar located for "amount" (float) on the Hermite spline defined by the scalars "value1", "value3", "tangent1", "tangent2".
spline value
spline value
spline value
spline value
input value
hermite result
Calculates the linear parameter t that produces the interpolant value within the range [a, b].
start value
target value
value between a and b
the inverseLerp value
Creates a new scalar with values linearly interpolated of "amount" between the start scalar and the end scalar.
start value
target value
amount to lerp between
the lerped value
Same as Lerp but makes sure the values interpolate correctly when they wrap around 360 degrees. The parameter t is clamped to the range [0, 1]. Variables a and b are assumed to be in degrees.
start value
target value
amount to lerp between
the lerped value
the log2 of value.
the value to compute log2 of
the log2 of value.
Moves a value current towards target.
This is essentially the same as Mathf.Lerp but instead the function will ensure that the speed never exceeds maxDelta. Negative values of maxDelta pushes the value away from target.
current value
target value
max distance to move
resulting value
Same as MoveTowards but makes sure the values interpolate correctly when they wrap around 360 degrees.
Variables current and target are assumed to be in degrees. For optimization reasons, negative values of maxDelta are not supported and may cause oscillation. To push current away from a target angle, add 180 to that angle instead.
current value
target value
max distance to move
resulting angle
Normalize the value between 0.0 and 1.0 using min and max values
value to normalize
max to normalize between
min to normalize between
the normalized value
Returns the angle converted to equivalent value between -Math.PI and Math.PI radians.
The angle to normalize in radian.
The converted angle.
This function returns number that corresponds to the percentage in a given range.
PercentToRange(0.34,0,100) will return 34.
to convert to number
min range
max range
the number
PingPongs the value t, so that it is never larger than length and never smaller than 0.
value
length
The returned value will move back and forth between 0 and length
Returns a random float number between and min and max values
min value of random
max value of random
random value
This function returns percentage of a number in a given range.
RangeToPercent(40,20,60) will return 0.5 (50%) RangeToPercent(34,0,100) will return 0.34 (34%)
to convert to percentage
min range
max range
the percentage
Loops the value, so that it is never larger than length and never smaller than 0.
This is similar to the modulo operator but it works with floating point numbers. For example, using 3.0 for t and 2.5 for length, the result would be 0.5. With t = 5 and length = 2.5, the result would be 0.0. Note, however, that the behaviour is not defined for negative numbers as it is for the modulo operator
the value
the length
the looped value
Returns -1 if value is negative and +1 is value is positive.
the value
the value itself if it's equal to zero.
Interpolates between min and max with smoothing at the limits.
This function interpolates between min and max in a similar way to Lerp. However, the interpolation will gradually speed up from the start and slow down toward the end. This is useful for creating natural-looking animation, fading and other transitions.
from
to
value
the smooth stepped value
Returns a string : the upper case translation of the number i to hexadecimal.
number
the upper case translation of the number i to hexadecimal.
Boolean : true if the absolute difference between a and b is lower than epsilon (default = 1.401298E-45)
number
number
(default = 1.401298E-45)
true if the absolute difference between a and b is lower than epsilon (default = 1.401298E-45)
Scalar computation library


| fkMapping reference pages |
coords=FILTERCOORDS(coords,filters) [coords,idx]=FILTERCOORDS(...)
coords=FILTERCOORDS(coords,filters) returns only those coordinates that are retained by the set of filters. The filters argument is a cell array with function handles for each dimension (column) of the coordinates array.
[coords,idx]=FILTERCOORDS(...) also returns the logical index array used for filtering.
| plot_map2D | Toolbox page | map |


public class SortField extends Object implements Serializable
Created: Feb 11, 2004 1:25:29 PM
Sort
,
Serialized Form
| Modifier and Type | Field and Description |
|---|---|
static int
|
BYTE
Sort using term values as encoded Bytes.
|
static int
|
CUSTOM
Sort using a custom Comparator.
|
static int
|
DOC
Sort by document number (index order).
|
static int
|
DOUBLE
Sort using term values as encoded Doubles.
|
static
SortField
|
FIELD_DOC
Represents sorting by document number (index order).
|
static
SortField
|
FIELD_SCORE
Represents sorting by document score (relevance).
|
static int
|
FLOAT
Sort using term values as encoded Floats.
|
static int
|
INT
Sort using term values as encoded Integers.
|
static int
|
LONG
Sort using term values as encoded Longs.
|
static int
|
SCORE
Sort by document score (relevance).
|
static int
|
SHORT
Sort using term values as encoded Shorts.
|
static int
|
STRING
Sort using term values as Strings.
|
static int
|
STRING_VAL
Sort using term values as Strings, but comparing by
value (using String.compareTo) for all comparisons.
|
| Constructor and Description |
|---|
SortField
(
String
field,
FieldCache.Parser
parser)
Creates a sort by terms in the given field, parsed
to numeric values using a custom
FieldCache.Parser
.
|
SortField
(
String
field,
FieldCache.Parser
parser,
boolean reverse)
Creates a sort, possibly in reverse, by terms in the given field, parsed
to numeric values using a custom
FieldCache.Parser
.
|
SortField
(
String
field,
FieldComparatorSource
comparator)
Creates a sort with a custom comparison function.
|
SortField
(
String
field,
FieldComparatorSource
comparator,
boolean reverse)
Creates a sort, possibly in reverse, with a custom comparison function.
|
SortField
(
String
field,
int type)
Creates a sort by terms in the given field with the type of term
values explicitly given.
|
SortField
(
String
field,
int type,
boolean reverse)
Creates a sort, possibly in reverse, by terms in the given field with the
type of term values explicitly given.
|
SortField
(
String
field,
Locale
locale)
Creates a sort by terms in the given field sorted
according to the given locale.
|
SortField
(
String
field,
Locale
locale,
boolean reverse)
Creates a sort, possibly in reverse, by terms in the given field sorted
according to the given locale.
|
| Modifier and Type | Method and Description |
|---|---|
boolean
|
equals
(
Object
o)
Returns true if
o
is equal to this.
|
FieldComparator
>
|
getComparator
(int numHits,
int sortPos)
Returns the
FieldComparator
to use for
sorting.
|
FieldComparatorSource
|
getComparatorSource
()
Returns the
FieldComparatorSource
used for
custom sorting
|
String
|
getField
()
Returns the name of the field.
|
Locale
|
getLocale
()
Returns the Locale by which term values are interpreted.
|
FieldCache.Parser
|
getParser
()
Returns the instance of a
FieldCache
parser that fits to the given sort type.
|
boolean
|
getReverse
()
Returns whether the sort should be reversed.
|
int
|
getType
()
Returns the type of contents in the field.
|
int
|
hashCode
()
Returns true if
o
is equal to this.
|
SortField
|
setMissingValue
(
Object
missingValue)
Set a default sorting value for documents which lacks one
|
String
|
toString
()
|
public static final int SCORE
public static final int DOC
public static final int STRING
public static final int INT
public static final int FLOAT
public static final int LONG
public static final int DOUBLE
public static final int SHORT
public static final int CUSTOM
public static final int BYTE
public static final int STRING_VAL
STRING
, which
uses ordinals to do the sorting.
public static final SortField FIELD_SCORE
public static final SortField FIELD_DOC
public SortField( String field, int type)
field
- Name of field to sort by. Can be
null
if
type
is SCORE or DOC.
type
- Type of values in the terms.
public SortField( String field, int type, boolean reverse)
field
- Name of field to sort by. Can be
null
if
type
is SCORE or DOC.
type
- Type of values in the terms.
reverse
- True if natural order should be reversed.
public SortField( String field, FieldCache.Parser parser)
FieldCache.Parser
.
field
- Name of field to sort by. Must not be null.
parser
- Instance of a
FieldCache.Parser
,
which must subclass one of the existing numeric
parsers from
FieldCache
. Sort type is inferred
by testing which numeric parser the parser subclasses.
IllegalArgumentException
- if the parser fails to
subclass an existing numeric parser, or field is null
public SortField( String field, FieldCache.Parser parser, boolean reverse)
FieldCache.Parser
.
field
- Name of field to sort by. Must not be null.
parser
- Instance of a
FieldCache.Parser
,
which must subclass one of the existing numeric
parsers from
FieldCache
. Sort type is inferred
by testing which numeric parser the parser subclasses.
reverse
- True if natural order should be reversed.
IllegalArgumentException
- if the parser fails to
subclass an existing numeric parser, or field is null
public SortField( String field, Locale locale)
field
- Name of field to sort by, cannot be
null
.
locale
- Locale of values in the field.
public SortField( String field, Locale locale, boolean reverse)
field
- Name of field to sort by, cannot be
null
.
locale
- Locale of values in the field.
public SortField( String field, FieldComparatorSource comparator)
field
- Name of field to sort by; cannot be
null
.
comparator
- Returns a comparator for sorting hits.
public SortField( String field, FieldComparatorSource comparator, boolean reverse)
field
- Name of field to sort by; cannot be
null
.
comparator
- Returns a comparator for sorting hits.
reverse
- True if natural order should be reversed.
public SortField setMissingValue( Object missingValue)
public String getField()
null
if the sort is by SCORE or DOC.
null
.
public int getType()
public Locale getLocale()
null
if no Locale was specified.
null
.
public FieldCache.Parser getParser()
FieldCache
parser that fits to the given sort type.
May return
null
if no parser was specified. Sorting is using the default parser then.
FieldCache
parser, or
null
.
public boolean getReverse()
public FieldComparatorSource getComparatorSource()
FieldComparatorSource
used for
custom sorting
public boolean equals( Object o)
o
is equal to this. If a
FieldComparatorSource
or
FieldCache.Parser
was provided, it must properly
implement equals (unless a singleton is always used).
public int hashCode()
o
is equal to this. If a
FieldComparatorSource
or
FieldCache.Parser
was provided, it must properly
implement hashCode (unless a singleton is always
used).
public FieldComparator > getComparator(int numHits, int sortPos) throws IOException
FieldComparator
to use for
sorting.
numHits
- number of top hits the queue will store
sortPos
- position of this SortField within
Sort
. The comparator is primary if sortPos==0,
secondary if sortPos==1, etc. Some comparators can
optimize themselves when they are the primary sort.
FieldComparator
to use when sorting
IOException


We want to show you what we can do!
L2B&Co can help you test concepts, specific features or process and even whole
business model. Every situation is different, and every research need requires
customization of our approach. That’s what makes this interesting for us.
With that in mind, please have a look at a sample report. We cannot and do not
share any work that we do for clients, so this is one we did on our own to
illustrate the detail and quality you can expect. Your specific questions and
insights will vary.
Just participate to answer our five minutes questionnaire and , you’ll receive
a download link in your email.


MUSICAL COMEDY MURDERS OF 1940
May 18-20, 2002
Directed by Jennifer Coghlan
THE CAST
Marjorie Baverstock - Jennifer Coghlan
Patrick O'Reilly - Russ Cannon
Ken DeLa Maize - Austin Stewart
Nikki Crandall - Mary Elizabeth Chambers
Roger Hopewell - Ben Weber
Eddie - Patrick Horne
Helsa - Katy McCraw
Elsa vonGrossenkneuten - Anjie Price
Sgt. Micheal Kelly - Russell Hehn
Bernice Rath - Kristen Welch


In mathematics, an elementary matrix is a matrix which differs from the identity matrix by one single elementary row operation. The elementary matrices generate the general linear group of invertible matrices. Left multiplication (pre-multiplication) by an elementary matrix represents elementary row operations, while right multiplication (post-multiplication) represents elementary column operations.
线性代数中，初等矩阵（又称为基本矩阵）是一个与单位矩阵只有微小区别的矩阵。具体来说，一个n阶单位矩阵E经过一次初等行变换或一次初等列变换所得矩阵称为n阶初等矩阵。
單位矩陣
來的，所以必須是個 n*n 的方陣。初等矩阵分为3种类型，分别对应着3种不同的行/列变换。


LIST Topographic Basemap (
Openlayers Version 2
)
Web Service Endpoint:
http://services.thelist.tas.gov.au/arcgis/rest/services/Basemaps/Topographic/ImageServer


Begone Birds
Birds can be a real problem from pooping on cars to ruining gardens, or just being flat out annoying.Here are a couple ways to rid your backyard, garden, ect. of birds. These ways vary from capturing them or just doing a little planting to get rid of these pests.
- Black birds ,a common bird are afraid of the color yellow so, planting yellow flowers in a backyard or garden should help.
- Setting traps is always an efficent way of getting rid of birds. (here's a link on how to catch them)
- Starlings,another common bird are startled by mirrors and flashing lights so having those wouldn't hurt.
- Set up a small speaker that emits a sound of a bird that has spotted a predator when a motion senser is set up.
- Birds are highly aggravated by scented candles,the essential oils cause the birds nostrils and throat to be irritated.
Why?
Most common birds hold diseases that can infect you and in some cases,can be fatal.(here's a link to a website about bird diseases). Birds also do things that are just plain annoying,like pooping on cars or even destroying crops.