Love and Basketball Rated [PG-13], 120 minutes Starring Omar Epps and Sanaa Lathan; Alfre Woodard, Dennis Haysbert, Debbi Morgan, and Kyla Pratt. Written and Directed by Gina Prince-Bythewood website: www.loveandbasketball.com/
IN SHORT: a color blind GenX dateflick
Tracking the life stories of two childhood neighbors as they age and make their way towards lives as professional basketball players, Love and Basketball is the movie producer Spike Lee wanted last year's The Best Man to be, a flick staffed by an African-American cast whose appeal is color blind. That may be because what little rap slang is in the flick is easily translatable by middle aged white guys like Cranky or because stories of true love, in which the couple to be don't necessarily like each other for most of the story, are old hat and don't require much to figure out way in advance. That leaves the question of whether there is chemistry between the stars (there is) and whether the performances are interesting enough to sustain you (they are).
The bigger problem with writer/director Gina Prince-Bythewood's creation is that she slaps soundtrack songs over the action (literally) every five minutes or so. This may be a wonderful marketing tool for the soundtrack CD, which often outsells box office tickets, but it's irritating as hell to a grownup audience. Which would be me. At least the [PG-13] rating means the soundtrack free of obscenity laden rap songs. Cranky can't vouch for the CD.
Starting in 1981 at age eleven, we meet Quincy McCall (played as a youngster by Glenndon Chatman), son of NBA star Zeke (Dennis Haysbert) who is determined to follow in his dad's footsteps, with his dad's number on his back. The just moved in tomboy neighbor Monica Wright (ditto Kyla Pratt) who is determined to be the first femme player in the NBA and is already kicking out enough punk attitude fit to put any competitor in his place. Their first game results in physical damage to Monica. Their first relationship lasts about fifteen seconds. This "first quarter" of the movie lays out all that follows. Jump forward to senior year in high school, where Quincy (Omar Epps) is the hoop star and hottest high school prospect in the country. Monica (Sanaa Latham), still reeking of attitude and lacking in team spirit, can't get a recruiter to look her way. The parental units on both sides (Haysbert and Debbi Morgan; Alfre Woodard and Harry J. Lennix) both want their kidlets to get an education; the McCalls knowing that a pro career is a temporary fix at best, the Wrights knowing that there's no foreseeable place for a woman in the NBA.
The story continues into college, where both play for USC, and beyond. With one plot twist to keep it all interesting, you can figure out Prince-Bythewood's story with a careful analysis of the above paragraph. If you don't want to expend the brain power, everything to come should ring clear as a bell about halfway through the flick.
On average, a first run movie ticket will run you Eight Bucks. Were Cranky able to set his own price to Love and Basketball, he would have paid...
$5.00
A average dateflick for the teens and GenXers is what Love and Basketball is. There's little here to interest us old farts.
The Cranky Critic® is a Registered Trademark of, and Copyright © 2000 by, Chuck Schwartz. All Rights Reserved. Cranky on the web at www.crankycritic.com
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


"the foundation of healthy crop"
of your decisions record - breaking yields begin with soil sampling.


Home
Tours
About
Pages
Gallery
Blog
Contacts
Best tours and travel
Best tours and travel is the best tours and travel
Your Destination
Arrival › Departure
Your Budget ($)
Search
Hot Tours
So hot u might be burned lol


It is not enough for the Internet to succeed. It must succeed inevitably.
Or so many of us Internet Triumphalists in the mid-1990s thought. For, if the march of the Internet's new values were not unstoppable, then it would surely be stopped by our age-old inclinations and power structures. The Net, as we called it then, would become just another venue for the familiar patterns of marginalization, exclusion, oppression, and ignorance.
Now I'm afraid the argument for inevitability that kept me, and others, hopeful for 20 years no longer holds.
We have a responsibility to try to prevent our governments from passing laws that hand the Internet over to the companies that provide access to it, or that remove by fiat what engineers have granted us through software and protocols. We have a responsibility to try to prevent our governments from passing laws that hand the Internet over to the companies that provide access to it, or that remove by fiat what engineers have granted us through software and protocols. We have a responsibility to try to prevent our governments from passing laws that hand the Internet over to the companies that provide access to it, or that remove by fiat what engineers have granted us through software and protocols.
It is not enough for the Internet to succeed. It must succeed inevitably.
Or so many of us Internet Triumphalists in the mid-1990s thought. For, if the march of the Internet's new values were not unstoppable, then it would surely be stopped by our age-old inclinations and power structures. The Net, as we called it then, would become just another venue for the familiar patterns of marginalization, exclusion, oppression, and ignorance.
Now I'm afraid the argument for inevitability that kept me, and others, hopeful for 20 years no longer holds.
We have a responsibility to try to prevent our governments from passing laws that hand the Internet over to the companies that provide access to it, or that remove by fiat what engineers have granted us through software and protocols. We have a responsibility to try to prevent our governments from passing laws that hand the Internet over to the companies that provide access to it, or that remove by fiat what engineers have granted us through software and protocols. We have a responsibility to try to prevent our governments from passing laws that hand the Internet over to the companies that provide access to it, or that remove by fiat what engineers have granted us through software and protocols.
It is not enough for the Internet to succeed. It must succeed inevitably.
Or so many of us Internet Triumphalists in the mid-1990s thought. For, if the march of the Internet's new values were not unstoppable, then it would surely be stopped by our age-old inclinations and power structures. The Net, as we called it then, would become just another venue for the familiar patterns of marginalization, exclusion, oppression, and ignorance.
Now I'm afraid the argument for inevitability that kept me, and others, hopeful for 20 years no longer holds.
We have a responsibility to try to prevent our governments from passing laws that hand the Internet over to the companies that provide access to it, or that remove by fiat what engineers have granted us through software and protocols. We have a responsibility to try to prevent our governments from passing laws that hand the Internet over to the companies that provide access to it, or that remove by fiat what engineers have granted us through software and protocols. We have a responsibility to try to prevent our governments from passing laws that hand the Internet over to the companies that provide access to it, or that remove by fiat what engineers have granted us through software and protocols.


Home
Services
Back to the future
Tere Liye
We are gRoot
Blog
About Us
Our Mission
Our Team
Contact Us
Home
Services
Back to the future
Tere Liye
We are gRoot
Blog
Know us
About Us
Our Mission
Our Team
Contact Us
14
August
Mukesh Ambani’s Reliance Working From Home
Mukesh Ambani surpasses Elon Musk to become the 5th richest man in the world and there are no signs of slowing down for this man.
- Aman Priyaraj | NurtureCult | 14th August 2020
Subscribe to newsletter
Please fill the field.
See you in the mailbox!
SUBSCRIBE
Tags
Finance
Reliance
Facebook
Stock Market
Lockdown
Investment


After a bit of outdoors laziness of recent, this weekend I am going to kick start 2009 with a 25 miler in the Lakes split over this Saturday and Sunday. My single NY resolution this year is to do a 25+ miler once a month, every month.
I have booked next Monday off work, and am partially copying Bearded Git’s walk from a couple of years ago.
Friday night will see me camp at Sykeside to acclimatize to Winter camping. A hopefully faff-free morning will see me leave early to walk over Beda fell and onto the north end of High Street. A bit of wandering up High Street to Swarthbeck will hopefully find me a nice rest spot.
After an obviously quiet and good nights sleep (yeah right!), a Wayfayer’s bean and bacon breakie will power me on up High Street, past High Raise but only to The Knott. Here, weather permitting, I reckon a nice sit down to emerge myself further into nature will allow me my first Golden Eagle viewing (yeah right!!). Then my well rehearsed descent past Satura Crag will dump me at Angle Tarn for my third and final trip camp.
Monday morning will see the easy descent down Hayeswater Gill and back to the campsite to pack the trusty Volvo and a journey back home via the effortless, flowing M6 (yeah right!!! (Promise thats my last yeah right (yeah right!!!!)).
My biggest current concern is how, and whether I can get all my intended kit into my Deuter 32l sack. I failed when I tried last weekend, so I am revising kit list to see whether there is anything I don’t need, and figure whether i can pack it a little more intelligently. Um…


Enable this option to customise the Secrets Manager client(s) used to access secrets.
The most common use case is to access secrets in other accounts using IAM cross-account roles. In this setup, Jenkins performs *same-account* secrets access with its IAM principal's *implicit* role, and performs *cross-account* secrets access with *explicit* roles.
With custom clients, you can decide:
The plugin de-duplicates client configurations (where two clients have the same credentials provider, endpoint configuration, and region) when you save the Jenkins configuration. This helps you to avoid redundant clients.
For each client:


Through ongoing service, sound advice and direct access to a variety of investment products, Altoro Mutual can help you develop and reach your financial goals.
Whether you're looking for a short-term solution or a long-term investment strategy, Altoro Mutual offers a full range of account options to help you manage your investments including:
For more information about these products, please contact Altoro Mutual.
This page was last updated on: 10/30/2006


Bill 44-19
May 1, 2019
For the purpose of increasing the annual income tax to 2.81%.
ARTICLE 4. FINANCE, TAXATION, AND BUDGET
TITLE4. INCOME TAX
4-4-101. Income tax.
An annual income tax of [2.50%] 2.81% of an individual’s Maryland taxable income is levied on residents of the County.


{% extends "base.html" %} {% block title %}Work on Class2Go{% endblock title %} {% load url from future %} {% block bodytag %}
{% endblock bodytag %} {% block m_column_content %}We began building Class2Go this past summer and now now have hordes of students taking Stanford classes for free.
Our stack is modern and sane: Python/Django and MySQL on the backend, Bootstrap, jQuery, Popcorn (and others) on the frontend. We bring up machines quickly in AWS with Chef.
All our source is on GitHub. Our bug list is there too. It's fun to work in a small team that can move fast — we ship weekly (at least!). And the Stanford campus is a cool place to work.
Local (or willing to re-locate) applicants only please.
Bring more client-side savvy to our site by developing in 80% Javascript and 20% Python. Use modern toolkits (e.g. backbone, require, underscore...) to make our site functional, beautiful, and engaging.
This engineer should be passionate about reliable and scalable cloud systems. Do you know the right way to build things, but never gotten the chance to do it right?
They will also be the team's release engineer. We need someone to set up code management and process for a codebase used by universities across the world.
We are looking for three skills:


|
Evolutionary Diversification in Anolis Lizards
|
Represents single run. More...
#include <simulation.hpp>
Public Member Functions | |
| Simulation (int argc, char *argv[]) | |
| Parse command arguments. | |
| ~Simulation () | |
| destructor in cpp for incomplete type | |
| void | run () |
| Top level function that should be called from main() | |
Private Member Functions | |
| void | evolve () |
| Call life_cycle() repeatedly. | |
| void | life_cycle () |
| One step forward. More... | |
| void | write_snapshot (const size_t time, std::ostream &ost) const |
| output genotype frequencies for each patch | |
Private Attributes | |
| std::vector< std::vector< Patch > > | population |
| Two-dimensional matrix of Patch. | |
| bool | verbose_ = false |
| Print verbose output. | |
Represents single run.


Oscilloscope demo application. Uses the demo sensor - change the new DemoSensorC() instantiation if you want something else. See README.txt file in this directory for usage instructions.


Event History: Entities Page
This tab page of the Event History dialog shows the history of all entities in the current game, including those that were already eliminated.
- The Entity List shows the internal identifiers of all entities.
- All identifiers are composed of an entity class identifier (up to the final dash) and an instance count (after the final dash).
- The list entries are sorted alphabetically by entity class identifiers, and numerically by instance counts within the same entity class.
- Left-click on an entry to select it. The Event List reflects the selected entry.
- The Event List shows the internal “events” that Hexkit recorded for the selected entity.
- Turn shows the game turn during which the event was recorded.
- Event shows the type of the event.
- Create means that the entity was created.
- Delete means that the entity was deleted from the game.
- SetName means that the entity’s instance name has changed.
- Value shows other data associated with the event. This is usually the active faction at the time of the event, but it is the new instance name for the SetName event.
- Drag the vertical splitter between Entity List and Event List to adjust their respective share of the current dialog width.
- See Event History for a description of other controls in this dialog.
Remarks
All entities that were created by the scenario, and possibly by the Faction.Initialize
method if it was overriden in the rule script, will appear with a Create event during the first turn and with the first active faction.


es
.
weso
utils
package
utils
Visibility
Public
All
Type Members
final
case class
NotParsed
[
B
]
(
error:
B
)
extends
ParserReport
[
Nothing
,
B
] with
Product
with
Serializable
final
case class
Parsed
[
A
]
(
info:
A
)
extends
ParserReport
[
A
,
Nothing
] with
Product
with
Serializable
sealed abstract
class
ParserReport
[
+A
,
+B
]
extends
AnyRef
sealed abstract
class
RDFSyntax
extends
AnyRef
Value Members
object
IOUtils
object
JSONLD
extends
RDFSyntax
with
Product
with
Serializable
object
JenaUtils
object
NTriples
extends
RDFSyntax
with
Product
with
Serializable
object
RDFSyntax
object
RDFUtils
object
RDFXML
extends
RDFSyntax
with
Product
with
Serializable
object
TURTLE
extends
RDFSyntax
with
Product
with
Serializable
object
Unknown
extends
RDFSyntax
with
Product
with
Serializable
Ungrouped


Employee ID: 012345
Email<EMAIL_ADDRESS>Office Number: A123
Employee ID: 654321
Email<EMAIL_ADDRESS>GitHub: msr102087
Employee ID: 0000
Email<EMAIL_ADDRESS>School: University of Washington


This year, the UW iGEM team has created the Chromastat: an affordable, modular, and autonomous turbidostat + color detector. Our hardware project began with a review of the UW iGEM 2016’s designs and concepts. The general idea of a control system had been suggested, but not yet implemented. Because the project required an improvement of the pump, a set of sensors, and a system of responsive real-time control, we decided to begin by dividing the task into the following categories and domains of responsibility:
| Task | Responsibility |
|---|---|
| Sensors | Choosing appropriate sensor hardware and designing ways to attach them. |
| Pumps and Fluids | Improvement of the syringe pump design, with focus on accuracy. |
| Tank | Research methods of delivering inducer and media fluids into the bioreactor beaker and removing waste products. |
| Integration | Design response and control software, and create a user-friendly interface that runs on a Raspberry Pi. |
The parts list for our project can be found here: http://2017.igem.org/wiki/images/f/f2/T--Washington--PartsList.xlsx
Figure: Raspberry Pi
The Raspberry Pi is an inexpensive, credit card-sized computer. It runs on a variant of the open-source operating system, Linux. This means that it allows the use of any major programming language. A Raspberry Pi can be operated by connecting a keyboard and monitor, or by accessing it remotely with a PC or major smart phone. This ease of access allowed us to choose between a broad range of approaches for software control. We chose the popular Java Swing user interface platform as our way for the user to configure and operate the system.
The general solution follows from connecting the Raspberry Pi’s low power logic system (“GPIO” pins) to a simple integrated circuit capable of turning device components on and off as required. Through our easy-to-use Java software, a user can control all of these components without the need for any special technical knowledge.
The Raspberry Pi itself is a low-voltage logic system that cannot provide much power. In our device, the Pi is connected to a circuit board that allows this low-voltage logic to control more power-intensive devices such as a heater, bubbler, and magnetic stirrer. Power to these devices comes from a low-cost PC power supply of the kind used in inexpensive desktop computers.
Documentation for the sensors: https://github.com/uwigem/uwigem2017/tree/master/docs/specSheets
Our syringe pump was custom designed from the ground up, is open source and 3D printable, and is cost effective. Industrial syringe pumps with the feature set that we provide (high accuracy, programmability, and automatic refilling) cost around $1000, whereas our creation only costs around $80 total to create and assemble, provided that a 3D printer is available. Because the accuracy of our pump comes from the linear actuator (stepper motor and drive assembly), the accuracy varies by syringe size. This allows the user to choose between a larger, slightly less accurate syringe or a smaller more accurate one. Software calibration makes it easy for the software to adjust to nearly any standard syringe size. Using a standard 3mL syringe, our pump is accurate to +/- .01 mL for any given dispense action.
To read about our Syringe Pump design process, please check out our Design page.
Find the STEP files for our open source syringe pump here: Syringe Pump STEP files
To aerate our culture we chose an aquarium pump, the Stellar Air Pump S-30, which retails for around $15. We modified the power plug to be controllable by solid state relay from the Raspberry Pi. We placed a 0.1μm filter in-line between the pump and culture to reduce contamination.
We wanted to ensure that the system would not only be aerated, but well-mixed. The assumption of being well-mixed is built into our sensing apparatus, so it was important to use a system that could keep the culture mixed thoroughly without exposing it to contaminants.
This is achieved using a magnetic spinner to suspend the culture. We used a magnetic spin bar inside the culture and controlled that from the underside with a custom printed platform using inexpensive disc magnets and a lightweight motor.
The primary difficulty we encountered when assembling a low-cost magnetic stirrer was that most inexpensive electric motors revolve too quickly to effectively stir the solution. . A motor that spins at 3,000 RPM, for instance, can be obtained for about $5. We reduced the motor by controlling its activation with a transistor and turning it on and off rapidly via software on the Pi. This implements pulse width modulation.
Find the STEP files for our open source magnet spinner attachment here: 3D Printed Spin Vane Stirrer
The enclosure is a structure created from aluminum metal and acrylic (Plexiglas) windows. It houses the three syringe pumps, culture tube, magnet spinner, aerator, Raspberry Pi, sensors, and custom circuit board.
Aluminum extrusion for the frame was purchased from a hardware store at a low price, and Plexiglas sheets were purchased from a scrap heap. We were donated some aluminum metal from a drylab member’s old robotics team, Punahou School Robotics.
The main goal of the enclosure is to be modular. The front and top panel can open to immediately give us access to the culture tube and the electronics in case there is an error. Sitting on a top shelf is the Raspberry Pi and circuit board, which can be slid on and off with ease. On a secondary shelf is a 3d printed mount for the culture tube to sit in. This shelf also will store the inducers and media required for the culture. On the bottom shelf is the power supply, the magnet spinner, and the aerator. Finally, on the outside side panel are the three syringe pumps
Find the STEP Files for our open source Enclosure here: Enclosure STEP Files


UIModalController
The UIModalController
component listens for events on one child view component to hide or show another child view component.
class UIModalController
extends
UIRenderableController
Renderable wrapper for a single component that can be used to display another component as a modal view. The modal component is created immediately after the ShowModal
event is emitted, and removed when the CloseModal
event is emitted.
Constructor
(content?:
UIRenderable
): UIModalController
.onShowModal()
(): boolean
Handle ‘ShowModal’ events delegated from content components, by creating the modal component.
.onCloseModal()
(): boolean
Handle ‘CloseModal’ events delegated from content or modal components, by removing the modal component.
.showModal()
(): void
Show the (preset) modal component.
.closeModal()
(): void
Remove the currently showing modal component, if any.
.modal
The current modal component to be displayed, as a managed child reference, or undefined if the modal component is currently not displayed.
.placement
Modal view placement, defaults to Dialog.
.modalShadeOpacity
number
Modal backdrop opacity (0-1).
.renderContext
Inherited from UIRenderableController.renderContext
.
.content
TContent
Inherited from UIRenderableController.content
.
.delegateEvent() protected
(e:
ManagedEvent
, propertyName: string): true
Inherited from UIRenderableController.delegateEvent
.
.render()
(callback?: RenderCallback<Output<
UIRenderable
, any>>): void
Inherited from UIRenderableController.render
.
.isPresetComponent() protected
(): boolean
Inherited from Component.isPresetComponent
.
.getParentComponent()
<TParent extends Component = Component>(ParentClass?:
ComponentConstructor
<TParent>): TParent
Inherited from Component.getParentComponent
.
.getBoundParentComponent()
<TParent extends Component>(ParentClass?:
ComponentConstructor
<TParent>): TParent
Inherited from Component.getBoundParentComponent
.
.emitAction()
(name: string, inner?:
ManagedEvent
, context?:
ManagedObject
): void
Inherited from Component.emitAction
.
.propagateComponentEvent() deprecated
(name: string, inner?:
ManagedEvent
): void
Inherited from Component.propagateComponentEvent
.
.managedId
number
Inherited from ManagedObject.managedId
.
.managedState
Inherited from ManagedObject.managedState
.
.getReferenceCount() protected
(): number
Inherited from ManagedObject.getReferenceCount
.
.getManagedReferrers() protected
():
ManagedObject
[]
Inherited from ManagedObject.getManagedReferrers
.
.getManagedParent() protected
<TParent extends ManagedObject = ManagedObject>(ParentClass?:
ManagedObjectConstructor
<TParent>): TParent
Inherited from ManagedObject.getManagedParent
.
.emit()
<TEvent extends ManagedEvent = ManagedEvent, TConstructorArgs extends any[] = any[]>(e: string | TEvent | (new (...args: TConstructorArgs) => TEvent), ...constructorArgs: TConstructorArgs): this
Inherited from ManagedObject.emit
.
.emitChange()
(name?: string): void
Inherited from ManagedObject.emitChange
.
.propagateChildEvents() protected deprecated
(...types: ((new (...args: any[]) =>
ManagedEvent
) | ((e:
ManagedEvent
) => any))[]): this
Inherited from ManagedObject.propagateChildEvents
.
.activateManagedAsync() protected
(): Promise<any>
Inherited from ManagedObject.activateManagedAsync
.
.deactivateManagedAsync() protected
(): Promise<void>
Inherited from ManagedObject.deactivateManagedAsync
.
.destroyManagedAsync() protected
(): Promise<void>
Inherited from ManagedObject.destroyManagedAsync
.
.onManagedStateActivatingAsync() protected
(): Promise<void>
Inherited from ManagedObject.onManagedStateActivatingAsync
.
.onManagedStateActiveAsync() protected
(): Promise<void>
Inherited from ManagedObject.onManagedStateActiveAsync
.
.onManagedStateDeactivatingAsync() protected
(): Promise<void>
Inherited from ManagedObject.onManagedStateDeactivatingAsync
.
.onManagedStateInactiveAsync() protected
(): Promise<void>
Inherited from ManagedObject.onManagedStateInactiveAsync
.
.onManagedStateDestroyingAsync() protected
(): Promise<void>
Inherited from ManagedObject.onManagedStateDestroyingAsync
.
UIModalController.Presets
UIModalController presets type, for use with Component.with
.
.modal
Modal component constructor (can also be passed as an additional argument to Component.with
).
.placement
Modal view placement, defaults to Dialog.
.modalShadeOpacity
number
Modal backdrop opacity (0-1), defaults to 0.


Tenth Week of RC
Day 5: Two Weeks Left
April 26, 2019
Confession: I haven't blogged for most of the last two weeks. Since I need to catch up on blogs, and I also only have two weeks left at the Recurse Center (!), this seems like a good time to write more of a big-picture blog.
A few weeks ago I was on a coffee chat with a fellow Recurser in my batch, T.  ("Don't climb a tree unless you can get yourself out," said a supervising adult. They mostly listened.)
"What would you have done differently at Recurse?" T asked me.
"I don't think I have that many things I would have done differently," I said. "I did have some projects I let go, but that's okay, because part of coming to Recurse was about letting myself explore things."
But I also objected to the question. "Asking that makes it sound like Recurse is over."
"That's true," T said. "I guess whatever you wanted to do differently, you could just do it for the next four weeks."
And so, what am I going to do, differently or otherwise, for the next two weeks?
Overall, I feel really proud of how I've commmitted myself to Recurse. I've made a lot of headway on OpenOversight, which was one of my main goals for the program. As shown by this blog, I've also gotten better at tracking my measurable progress, which is a tactic that Julie Pagano recommends for >combatting imposter syndrome. Like I said to T, I have stepped away from some work I was doing earlier in the program. For example, I started out reading "Working Effectively with Legacy Code" by Michael Feathers, but I've stopped reading it in the last few weeks as I shifted to working on job applications. Once I've finished applying to jobs, I plan on starting to read it again.
For the next two weeks, I'm going to continue working on OpenOversight, with a few discrete goals for the rest of my time. I need to refactor the upload images functionality, and I'm hopeful that it shouldn't take too long. I also want to make a front-end tweak that will display information about officers' incidents without requiring users to do a page reload. Finally, and most excitingly, I'm gong to implement multifactor authentication. When I'm not working on OpenOversight, I still need to finish building the Flask server for the back-end of the EmoReply chrome extension.
Finally, I'm going to pair more during the next two weeks. There aren't many people in my batch working with Python and Flask, which has made it tricky to find pairing partners for OpenOversight. However, pairing with people who were new to the tech stack reminded me of how much I enjoy pairing. It's always valuable to talk through technical decisions with people who are new to a project, regardless of how well they know the relevant technologies. Also, since there are only two weeks left of us being together, I'm trying to maximize the time I spend with other Recursers. I'd say something cheesy, but that would make it sound like Recurse is over. And clearly, I'm not ready for that.


What are Treasury, Departments and Parliament busy with?
- National Treasury plans the budget strategy and process, taking into account the priorities set out by the department responsible for planning.
- Departments conducts reviews and analysis of departmental expenditure outcomes and budgets.
- Parliament needs to pass the Division of Revenue Bill with or without amendments within 35 days of the fiscal framework being adopted by Parliament. The Committees on Appropriations holds public hearings when deliberating the contents and recommendations to be included in its report on the division of revenue bill.
How can I participate?
- Make submissions to the Committees on Appropriations providing your input on the division of money across the three spheres of government.
- Participate in public hearings held by provincial legislatures to debate the Division of Revenue Act and decide on whether to assent to it.


{% extends 'base.html' %} {% load static %} {% block mutop %}
{% endblock %} {% block museum %}| Name | Species | Location | Time | Value | Month | Operation |
|---|---|---|---|---|---|---|
| Common Butterfly | Bug | Flying | 4AM - 7PM | 160 | September - June | |
| Bitterling | Fish | River | All day | 900 | November - March |


{% extends 'layout.html' %}
{% import 'forms.html' as forms %}
{% block content %}
Welcome to the ALMA Data Mining Toolkit Buildbot
{%- if project_name -%}
for the
{%- if project_url -%}
{{ project_name }}
{%- else -%}
{{ project_name }}
{%- endif -%}
project
{%- endif -%}
!
{% include 'motd.html' %}
Buildbot Resources
{% set item_class=cycler('alt', '') %}
The Waterfall Display will give you a
time-oriented summary of recent buildbot activity.
The Grid Display will give you a
developer-oriented summary of recent buildbot activity.
The Transposed Grid Display presents
the same information as the grid, but lists the revisions down the side.


White to play 22
pips White=167 Black=158
(CorrectAnswer= 0/0, ErrorScore= 0)
1. 24/22(2) 6/4(2) eq: +0.261 55.89% (G:16.37% B:0.76%) 44.11% (G:10.62% B:0.43%) 2. 13/11(2) 6/4(2) eq: +0.227 (-0.034) 55.56% (G:17.28% B:0.96%) 44.44% (G:13.84% B:0.76%) 3. 24/16* eq: +0.165 (-0.097) 54.20% (G:14.58% B:0.82%) 45.80% (G:13.22% B:0.50%) 4. 13/9 6/4(2) eq: +0.132 (-0.129) 53.70% (G:15.87% B:0.80%) 46.30% (G:13.47% B:0.70%) 5. 24/22 13/11 6/4(2) eq: +0.129 (-0.132) 54.09% (G:15.17% B:0.82%) 45.91% (G:13.99% B:0.59%)


Pressure Tracker
Login/Register
Login
Register
Settings
Logout
Login/Register
Login
Register
Logout
First SideNav
Second SideNav
My Health Entries
New Health Entry
How is your pain right now?
Current Pain
0 No Pain
1 Can be ignored
2 Mild Pain
3 Interferes with tasks
4 Moderate Pain
5 Interferes with concentration
6 Severe Pain
7 Interferes with basic needs
8 Bedrest Required
9 Worst Pain Possible
How is your mood right now?
Current Mood
1 Optimistic
2 Hopeful
3 Content
4 Bored
5 Pessimistic
6 Irritable
7 Disappointed
8 Hopeless
9 Depression
Note
Current Symtoms
Current Medication
Clear
Save
Pain and Mood
Barometric Pressure 02141
3 Months
1 Month
1 Week
1 Day
Please Register
Email
Password
Confirm Password
Already have an account?
Login
Please Login
Email
Password
No account yet?
Register


Makefile Project - Behavior page
Use the Behavior page in the Makefile Projects preference panel to define build behavior.
| Option | Description |
|---|---|
| Stop on first build error | Stops the build when an error occurs. |
| Use parallel build | Activate to generate parallel builds. |
| Use optimal jobs number | Activate to let the system determine the optimal number of parallel jobs to perform. |
| Use parallel jobs | Set the maximum number of parallel jobs to perform. |
| Build on resource save (Auto build) | Defines what the standard builder will call when a file is saved, it is not recommended to enable Auto Build for C/C++ projects. |
| Make build target | Define what the standard builder will call by default when told to build, rebuild, clean, etc. You can change these so that new projects will use different targets if the defaults are not appropriate. Click Variables to open the Select build variable dialog. |
| Build (Incremental build) | Defines what the standard builder will call when an incremental build is performed. |
| Clean | Defines what the standard builder will call when a clean is performed. |
Defining Project Build settings


Mobility23 - Websocket
Business Incident
Transport Booking
Vehicle
Vehicle Position
Vehicle Communication
Specification


Amazing Things
What is the most amazing thing you ever did?
Which is the most amazing thing on Earth?
What is the most amazing feeling?
What amazing things happen every minute?
Show me!


This inspection searches for task item marker followed by reference in files with Old GitHub Doc
lists parser option enabled.
In Old GitHub markdown, before the switch to CommonMark, a task item marker followed by a link reference was processed as a link reference with explicit text instead of a task list item marker followed by a reference.
As a work-around a
needs to be
inserted between the task item marker and the link reference.


Bibhub was designed first with a focus on students, honoring our first value, Build a better tomorrow. There are a lot of student frustrations around behavoir data, but they can be grouped into three general catagories; Opaqueness, Inconsistency, and Ineffectiveness.
Many students who struggle with behavoir, also struggle with understanding the behavoir data tracking that is often implemented as part of their BIP. Since it is often related to their rewards, this opaqueness can lead to more frustration and reduce buy-in. It can feel like the reward system is being done to them instead of earned by them. This feeling is sometimes expressed as being "just lucky" on a successful day, or "I'm always like this" on less successful days.
We all know how important consistency is to all students. Poorly managed behavoir data is inherently inconsistent! When data is incomplete, lost, misrecorded, or just late in getting reported it breaks the behavoir/feedback cycle. Worse, it does so in a stochastic manner. This errodes the trust, sometimes nominal to begin with, that a student has that the system is fair. If data only gets back to the Special Education Teacher on good days, or only on bad days, the system is out of balance.
The hands-down most demoralizing experience for the student is when it doesn't work. Biphub's foundation is simple logic, bad data + good intentions = bad decisions. Hope is a precious commodity for students who feel cronically unsuccessful. Being under a behavoir plan that they can't be successful at, or that doesn't target the correct antecedents or skill gaps reinforces the idea that they are the problem. Poorly managed behavoir data systems are inherently dangerous because they can give false positives, fail to show successes that are happening, or take to long to give the team the signal that the student can't be successful.
Bibhub has a strong focus on user experience, becuase it expresses our second value Easy to use creates effective use. Tearcher frustrations surrounding managing behavoir data are varied but, for the sake of symmetry, lets group them into three catagories; Manuel Labor, Veracity, and Inflexablity.
Most SPED teachers manage Bip data in the same way as it has been done for years, with paper. Whether it takes the form of observation logs, tracker sheets that travel with the child, or token economies, the common denominator is that the data is initially manefested in physical form. Apart from a not insignificant waste of paper resources, this means that the data is either never digitalize (not able to be graphed or queried), or has to be manuelly input into a spreadsheet program. Even the most brutally effecient systems put in place become unweildy under the sheer weight of the data to be input.
Beyond the waste of human capital in this process, to get the spreadsheet to give back meaningful data (averages, graphes, etc), the SPED teacher has to do some olympic level spreadsheet gymnastics. Most teachers were never trained to vault over pivot-tables or z-axis graphes. Even then, the data for each student is generally siloed into sperate tables, and lives locally on only one teachers computer. This makes it very difficult to compare data across a caseload/grade-level team to look for trend data.
One of the most common frustrations shared by teachers during the developement of BipHub, was that the data they got was often incomplete, didn't answer the question they needed answered, or to slow to be used well. Not knowing how a student was doing throughout the day, in real-time, meant that data conversations with students were to late in coming to turn a day around, or prevent an escalation.
Data that is collected on paper is often lost or damaged throughout the day, leaving gaps in the data, decreasing accountablity and skewing interretation of the data. Even then, paperbased data is often not input into the spreadsheet fast enough to keep the digital model up to date. This means the digital data is only useful for the short period of time when all of the data has been input, and no new data exists.
Finally, most BIP data systems are only able to ask one type of question, a qualitative scale recorded by an observe, ex. "Johny will keep his hands to hisself 1-5". However, there are lots of types of data that could be collected; incidence data (how many times did Johny successfully turn in papers?), time data (how long did Johny work independently?), boolean data (Did Johny get removed from class?), percentage data, (what percent of the exit ticket did johny complete?).
Getting the right answer often starts from asking the right question, and recording the right type of data is crucial to this. Further, getting a spreadsheet to understand time sensitive data as opposed to boolean data, or incidence data is nigh impossible. A flexible application supported by a rhobust database that can handle varied datatypes is crucial to well managed behavoir intervention data.
Behavoir intervention data is incredibly difficult to aggregate, because it is often siloed off by teacher, and individual to every student.This hampers collaboration and effective teamwork.. School leadership teams need better, more rhobust systems for gathering, interpreting, and acting on BIP data accross all gradelevels and teams.
One of the most consistent frustrations expressed by administrators is their inablity to quickly see an accurate picture of the effectiveness of interventions in place. School leaders need to be able to identify in real time the students, teachers, or teams that need more support. All school leaders recognize that the quicker this support becomes available the more effective it will be, but the turnaround time on current data management systems can mean weeks may go by before they are alerted to a problem.
Accurately documenting the services a student with a BIP recieved is ultimately the responsiblity and liablity of the school. Having secure, redundant and persistant data storage, alongside a exhaustive report generation suite is crucial to a rhobust documentation of services for every student.


Toggle navigation
Featured
Submit
X
{{link.id}}
{{track.user.username}} - {{track.title}}
View on SoundCloud
Play/Pause
{{ currentTime | hhmmss }} | {{ duration | hhmmss }}
{{ currentTime / duration || 0 }}
No song!
Loading...


[Erowid Warning: Our understanding of the literature is that there is no such thing as safe use of volatile solvents, aerosols and other street inhalants : their psychoactive effects are inseparable from nerve and organ damage. We have chosen to include these reports to help document the real world use of inhalants, but their inclusion is not intended to imply that they are anything but dangerous.]
I started using butane and propane and other forms of gas in August 2000. If I would know what I know now, I would never have started. This stuff was never intended for human consumption because it can kill.
I started blasting butane gas from deodorant, glade, and other aerosols out of curiousity on the effects. That was the biggest mistake of my life. For almost the next two years, I would struggle to kick this dangerous addiction with several relapses.
Inhalents are VERY potent and is it easy to lose control. I thought I could just take a little bit of the gas and then put it down but, I craved for more deadly quantities. I do actually get a high for a few seconds and then the bottom drops out. I could feel my brain cells frying from these poisons I was inhaling. After I was done, I had this killer headache and felt like my head was going to explode! I consider myself very luckly to be alive.
My wrong decision to use butane has gotten me arrested, put in jail, put on a cocktail of psychiatric drugs and mental institutions. I almost killed myself three times by inhaling the gases. I just had a frightening near death experience today May 9, 2002. This very well could have been the date on my tombstone.
I will never use again because I know next time I may not be so lucky. I plead with you never ever to use inhalents for they are poisons with deadly consequences. I want to tell anyone who is using or is thinking of using inhalants, don't do it! You could be dead after your first breath. Think of how devastated your family and friends would be. There are better things to do than to mess yourself up by sniffing poisons.
Experience Reports are the writings and opinions of the individual authors who submit them.
Some of the activities described are dangerous and/or illegal and none are recommended by Erowid.


Liz Peek and Jessica Tarlov respond to Carly Simon's #MeToo criticism
by Victor GarciaThe "Ladies Night" panel reacted to singer-songwriter Carly Simon's critique of the #MeToo movement on Friday on "The Story with Martha MacCallum."
Simon, who is promoting her memoir, "Touched By The Sun," told The Guardian that the movement has made it "dangerous for men to act like men."
“I welcome it and now I hope that it will go back to a position where things will be normalized,” Simon told the publication before voicing her concerns with #MeToo.
"Not that the men who go overboard and disrespect a woman are acting like men. You know what I mean.”
Fox News contributor Liz Peek agreed with Simon, saying the movement started in a "good place" but has gone "too far."
"I think we've kind of neutered American men," Peek said bluntly. "Look, how are you going to flirt?
Peek was referencing San Francisco 49ers quarterback Jimmy Garoppolo, who faced scrutiny on Twitter after it appeared he'd made a pass at Fox Sports' Erin Andrews following a football game on Thursday.
Andrews interviewed Garoppolo on the field, asking him how it felt to keep the winning streak going.
He answered: “It feels great, baby. Happy Halloween.”
CLICK HERE TO GET THE FOX NEWS APP
Democratic strategist Jessica Tarlov wasn't offended by the quarterback's comments but was concerned with "conflating" Simon's comments with real abuse claims.


Trader Espen:
Hey you... Do you or don't you have the treasure Map? You must have heard the rumor that I'm a great pirate aficionado. So, are you trying to rip me off? Get lost!


Home
About
Booking
Oktoberfest
Photos
Testimonials
Music
Videos
Music
Frank K Duo Selected Melodies
Listen
R&B
Swing
Oktoberfest
Latin Medley
With Keyboard, Accordion and Violin
Country
Standards
Ethnic Medley
Standards
Listen
Hallelujah
Don't Be that Way
Every Day I Have the Blues
My Eyes Adore You
It's a Wonderful World
New York State of Mind
You Belong to My Heart
Mack the Knife
Rock/Disco
Listen
I Love the Night Life
Believe in Love
Electric Slide
I Will Survive
Sea Cruise
Mustang Sally
Taking Care of Business
Ethnic Music (Accordion)
Listen
My Melody of Love Polka
German Polka
French Waltzes
Happy Wanderer
Wooden Heart
Julida Polka


Bee use several kind of data types described below. Use these links to jump to a particular data type. Use browser back-button to revisit a particular data type:
Bee is using a gradual typing system. We think dynamic typing is more fragile and prone to errors. Therefore Bee is a strongly typed language with type inference. That means any data is constrained by fixed "data type" rules.
Bee has predefined data types. You can create new data types based on predefined types using a type declaration. You can create sub-types or composite types having new constraints and rules that can improve data validation further.
A data type can be manipulated using rules and operators. You can have a variable of type: Type. To detect a data type of any variable you can use the introspection function type().
Primitive data types are defined using one capital letter. This may be unusual in Computer Science but standard in Mathematics. Therefore Bee uses this convention.
| Alias | Code | Description + Default representation |
|---|---|---|
| Boolean | B | Boolean or 8 bit number, 0 = False, >= 1 True |
| Alpha | A | Alpha-numeric E-ASCII ('0'..'9') ('a'..'Z') |
| Unicode | U | Unsigned 32 bit, max: U-FFFFFFFF (UTF32) |
| Rational | Q | Fix point representation number: like 1/2. Notation: Q(14,17) |
| Natural | N | Unsigned large positive integer 64 bit [0..+] |
| Integer | Z | Signed large integer 64 bit [-..+] Z(64) |
| Real | R | Double precision float 64 bit (-..+) R(64) |
These are symbolic representations for primitive data types:
| Example | Type | Literal characters |
|---|---|---|
| 'a' | A | (+-) & (0..9) & (a..z) & (A..Z) |
| 'Ω' | U | (Δ Λ Φ Γ Ψ Ω Σ Π π ⊥ ǁ α β ɣ ε δ μ ω ...) |
| "str" | S | (∀ UTF8) |
| 0B0,0B1 | B | (0,1) & B |
|<PHONE_NUMBER> | N | (0,1,2,3,4,5,6,7,8,9) |
| +0 | Z | (-+) & (0,1,2,3,4,5,6,7,8,9) |
| 'a','b' | A | ASCII (0x00..OxFF) |
| U+FFFF | U | (U+) & (0,1,2,3,4,5,6,7,8,9) & ABCDEF |
| U-FFFFFFFF | U | (U-) & (0,1,2,3,4,5,6,7,8,9) & ABCDEF |
| 0.05 | R | (-.) & (0,1,2,3,4,5,6,7,8,9) |
| -1/2 | Q | (-/) & (0,1,2,3,4,5,6,7,8,9) |
| 1E10 | R | (-1E)& (0,1,2,3,4,5,6,7,8,9) |
| 1e10 | R | (-1e)& (0,1,2,3,4,5,6,7,8,9) |
note
Special types have an alias starting with capital letter. These types are embeded in the language and contribute to language coherence. All these types are actually references to memory structures:
| Alias | Type | Description |
|---|---|---|
| Complex | C | Double precision pair of double float numbers (9r+9j) |
| String | S | UTF8 encoded double quoted string "α β ɣ ε δ μ ω" |
| Date | D | "DD/MM/YYYY" |
| Time | T | "hh:mm,ms" |
| Lambda | L | Lambda expression or function. |
Bee define a collection literal using a special notation based on brackets. These types are going to be explained later in another page. We mention these types here because they represent types.
| delimiter | collection types |
|---|---|
| () | List |
| [] | Array / Matrix |
| {} | Set / Map / Object / Ordinal |
User can define type alias using operators ":" and sub-types using operator "<:" (inheritance). Usr can specify type of variables explicit usin operator ∈
** declare new type alias
type Type_Identifier: type_descriptor <: super_type;
** declare variables using type alias
new var_name ∈ Type_Identifier;
** declare many variables using type alias
new var_name, var_name ... ∈ Type_Identifier;
A range is a notation that designate a sub-set of consecutive integer numbers between two limits: lower limit and upper limit included in round parenthesis and separated by two dots (..) or (!).
range ::= (min..max); range ::= (min.!max); -- exclude upper limit range ::= (min!.max); -- exclude lower limit
#integer domain
rule main:
print (0..5); -- 0,1,2,3,4,5
print (0.!5); -- 0,1,2,3,4
print (0!.5); -- 1,2,3,4,5
pass if 32667 ∈ (0..+); -- expect to pass
pass if -32668 ∈ (-..0); -- expect to pass
return;
Ranges can use symbols that are ASCII or Unicode. In this case the symbols must be included in single quotes: 'X' or use U+ notation:
** sub-type declarations
type .Digit: ('0'..'9') <: Z;
type .Capital: ('A'..'Z') <: A;
type .Lowercase:('a'..'z') <: A;
type .Latin: (U+0041..U+FB02) <: U;
rule main:
** following statements should pass
pass if '0' ∈ Digit;
fail if 'x' ∈ Capital;
pass if 'X' ∈ Capital;
pass if 'e' ∈ Latin;
return;
Domain is very similar to range except a domain has a ratio. This is the difference, the numbers are not integers, can be fractional or Q umber.
type Domain: (min..max:ratio) <: Super_Type;
** generate rational numbers
print (0..1:1&\4); -- 0&\4, 1&\4, 2&\4, 3&\4, 1
** generate float numbers
print (0..1:0.25); -- 0.00, 0.25, 0.50, 0.75, 1.00
Constants literals bound to identifiers using keyword "set".
** using explicit type
set constant_name: constant_literal ∈ type_name;
** using implicit type
set constant_name := constant_literal;
#define symbol constants
set forall1: U+2200 ∈ A; -- Symbol: ∀
set forall2: U-00002200 ∈ U; -- Symbol: ∀
Variables are defined using type inference and these operators:
| operator | purpose |
|---|---|
| ∈ | declare variable/element type |
| : | define | block start | pair up operator |
| : | set initial value (require type in declarations) |
| := | type inference | share a reference | assign operator |
| :: | deep copy | duplicate object | cloning operator |
** primitive variable declarations with type
new var_name ∈ type_name; -- declaration only type without initial value
new var_name: value ∈ type_name; -- declaration with initial value and type
** Variable declaration using type inference
new var_name := expression; -- expression ":=" do not require type hint ("∈").
** Multiple variables can be define in one single line using comma separator:
new var1, var2 ... ∈ TypeName; -- default initial values
new var1, var2 ... := Expression; -- use type inference for all initial values
** Initialize multiple variables, of the same type (type is required)
new var1:con1, var2:con2 ... ∈ TypeName;
One can modify variables using alter statement.
#fragment of code
new a:10, b:0 ∈ Z; -- initialize two variables
let b := a + 1; -- modify b using binding operator :=
let b += 1; -- modify b using modifier +=
expect b = 12; -- check if b has proper value
** declare a public constant
set .PI: 3.14 ∈ R;
rule main:
** declare a single variable
new a ∈ Z; -- Integer
** declare multiple variables
new (x,y):0 ∈ R; -- Double
new (q,p):0 ∈ L; -- Logic
** using modifiers
let a := 10; -- modify value of: a == 10
let a += 1; -- increment value of: a == 11
let a -= 1; -- decrement value of: a == 10
** modify two variables using one single constant
let x, y := 10.5;
** modify two variables using two constants
let q, p := True, False;
** swapping two variables
let p, q := q, p;
return;
When data type mismatch you must perform explicit conversion.
** data conversion
rule main:
new a:0, b:20 ∈ Z;
new v:10.5, x:0.0 ∈ R;
** explicit conversion
let a:=v :> N;
print a; -- truncated to 10
** explicit conversion
let x := b :> R;
print x; -- expect 20.00
return;
Bee define A as single UTF-8 code point with representation: U+HH
rule main:
new a, b ∈ A; -- ASCII
new x, y ∈ B; -- Binary integer
let a :='0'; -- ASCII symbol '0'
let x := a :> B; -- convert to binary 30
let y := 30; -- decimal code for '0'
let b := y :> A; -- convert to ASCII symbol '0'
return;
You can use symbol ":=" to initialize variables using type inference.
** declare constants
set i := 4; -- integer constant
set r := 2.5; -- real constant
set q := 1&\8; -- rational constant
** declare variables
new x := 0; -- integer number
new y := 0.0; -- real number
new z := 0\1; -- rational number
We can use variable type to validate expression type.
** using type inference
rule main:
new a := 0; -- integer variable
new b := 0.0; -- real variable
let a:= 10.5; -- error: explicit conversion is required
return;
You can use operator "∈" to verify data type:
rule main:
new a := 0 ∈ Z;
** expected: Integer
expect a ∈ Z;
return;
Boolean type is Bee is native numeric of type B. However we also implement native two constants True, False that are publicly available in core library
** overwrite the default values
set False = 0;
set True = 1;
Printing native Boolean values is going to print numbers. Type B can support a number between 0b0 and 0b00000001. Therefore printing this type is done using notation 0B0 and 0B1.
** printing Boolean values
rule main:
print False; -- 0B0
print True; -- 0B1
return;
You can convert B to a number, safely. You can convert a number to B explicit using cast operator: number :> B.
The number will loose all it's significance and become 0B1 or 0B0.
Bee uses several familiar logic operators from mathematics:
Precedence: { ¬, ∧, ∨ }. Symbol ¬ will apply first, symbol ∨ will apply last.
bitwise
In Bee we define special operators to perform bitwise operations. One opperator is overwrite: ⊕. This operator (xor) can operate on both, logical values or expressions and also on integer numbers.
# bitwise operations
print 4 | 3; -- out:7 is because 100 | 011 = 111 = 7;
print ~4; -- out:3 is because: 100 ~ 100 = 011 = 3;
print 4 & 7; -- out:4 is because: 100 & 111 = 100 = 4;
print 4 ⊕ 4; -- out:0 is because: 100 ⊕ 100 = 000 = 0;
print 1 << 2; -- out:2 is because: 001 << 2 = 100 = 4;
print 6 >> 2; -- out:1 is because: 110 >> 2 = 001 = 1;
Comparison operators will create a Boolean response: 1 = True or 0 = False. Also, the equivalent and belonging operators will create a Boolean response. You can combine them to create Boolean expressions.
rule main:
new (x, y):4 ∈ Z; -- primitive integer
** value comparison
print x = 4; -- 1 (equal)
print x ≡ 4; -- 1 (identical)
print x = y; -- 1 (equal)
print x ≡ y; -- 1
print x ≠ 5; -- 1 (different)
print x!≡ 5; -- 1 (not identical)
** reference ordering
print x ≥ y; -- 1: x and a are actually equal
print x ≥ 4; -- 1: greater or equivalent to 4
print x ≤ 4; -- 1: less than or equivalent to 4
print x > 4; -- 0: not greater than 4
print x < 4; -- 0: not less than 4
** arithmetic expressions have primitive results
print x - 4 = 0; -- 1
print x - 4 ≡ 0; -- 1
return;
singleton
Primitive types are unique. That means they are equivalent.
Logical expression have value { 0 = False, 1 = True }
** define constants based on Boolean values
set f: False;
set t: True;
rule main:
** expressions with single operant
print f; -- 0
print ¬ t; -- 0
** expressions with two operands
print (f = t); -- 0
print (f ≡ t); -- 0
print (f ≠ t); -- 1
print (f < t); -- 1
print (f > t); -- 0
print (f ∧ t); -- 0
print (f ∨ t); -- 1
print (f ⊕ t); -- 1
return;
coercion Any numeric expression can be converted to a logic value using coercion operator ":>" (easy to memorize if you think is like an arrow).
set (a: 0.0, b: 1.5) ∈ R;
rule main:
new (x, y) ∈ B;
let x := a :> B; -- 0
let y := b :> B; -- 1
return;
design
** logical values are numeric
print True ≡ 1; -- 1
print False ≡ 0; -- 1
** logical values do not compute
print False - True; -- Error
print True + True; -- Error
** Null value is not True
print Null ≡ True -- 0
** Null value is not False
print Null ≡ False -- 0
Type inference is a logical deduction of data type from constant literals.
Each literal has associated a default type, induced by operators {":=", "::"}.
** string expressions
new c := 'a' ; -- type = A
new s := '∈' ; -- type = U
new s := "str" ; -- type = S
** numeric expressions
new i := 0; -- type = Z
new j := 0.50; -- type = R
** define synonyms for logic constants
set f := False; -- type B
set t := True; -- type B
** multiple variables get same value
new (x, y, z) := 5; -- type = Z for all
** multiple variables get multiple values
new int, rea := -4, 4.44;
print type(int); -- Z
print type(rea); -- R
Composite structures are using () [] and {} to create different data types. Next you can study some examples. We wil explain later all these types: List, Map, Array, Object. All of these are also called Bee collections.
** boxed integer (type = Z)
new i := [10]; -- array of one value = 10!
** array with capacity of 4 integers: Z
new d := [1,2,3,4];
** array with capacity of 10 real numbers: R = 0.00
new e := [0.00](10);
** list of one value (Z)
new a := (1);
** list of integers (Z)
new b := (1,2);
** list of symbols (type = A)
new l := ('a','b');
** list of Unicode symbol (type = U)
new u := ("Δ", "Λ", "Γ");
** 2d matrix with capacity of 10x10 real numbers: R
new m := [0.00](10,10);
** 3d matrix with capacity of 10x10x10 reals: R = 0.00
new m := [0.00](10,10,10);
** data set of 4 integers: Z
new s := {1,2,3,4};
** hash map of (Integer: String)
new c := {1:"storage",2:"string"};
** object with two attributes: name ∈ S, age ∈ Z
new b := {name:"Goliath", age:30};
When we define parameters we can use type inference only for optional parameters. Mandatory parameters must have type declaration using ∈ symbol. If default value is not specified the parameter will have defailt zero initial value.
Optional Parameters:
** in rule foo, parameters a, b are optional.
rule foo(a: 0 ∈ Z, b: 0 ∈ Z) => (r ∈ Z):
let r := a + b;
rule;
rule main:
print foo(); -- 0
print foo(1); -- 1
print foo(1,2); -- 3
return;
Multiple parameters:
** parameters: a, b are mandatory, c is optional.
rule foo(a, b, c:0 ∈ Z) => (r ∈ Z):
let r := a + b + c;
return;
rule main:
print foo(1,2); -- 3
print foo(1,2,3); -- 6
print foo(1); -- Error: expected 2 arguments
return;
Pass arguments by name:
We can use parameter name and pair-up symbol ":" for argument value.
** rule with optional parameter (c)
rule bar(a, b, c:0 ∈ Z) => (result ∈ Z):
let result := a+b+c;
return;
** observe we use pair-up ":" to give value for each argument
rule main:
print bar( 1, 1 ); -- print 2 because c = 0
print bar( a:1, b:1, c:1 ); -- print 3 because c = 1
return;
In mathematics rational number is any number that can be expressed as the fraction p/q of two integer numbers: numerator "p" of type integer and a non-zero denominator "q" of type natural> 0.
Since "q" may be equal to 1, every binary integer is also a rational number.
Note: Q numbers are approximated numbers.
Other precision constants:
Literal Notation: p\q
It can be used with type inference to create Q numbers:
new x: 0 ∈ Q; -- 0
new a: 1\2 ∈ Q; -- 0.5
new b: 1\4 ∈ Q; -- 0.25
new c: 1\8 ∈ Q; -- 0.125
new d: 1\16 ∈ Q; -- 0.062
new e: 1\32 ∈ Q; -- 0.031
See also: wikipedia
Qm.n is m+n+1 bit signed integer container with n fractional bits.
Qm is a m+1 bit signed integer containing 0 fractional bits.
number of bits = m+n+1
precision is 2⁻ⁿ
range is [-(2ᵐ)..(2ᵐ-2⁻ⁿ)]
For example: Number format "Q5.2" can store in range (-32.00..31.75) on 8 bits.
new v ∈ Q5.2;
let v := -32; -- minim value
let v := 31.75; -- maxim value
See also: wikipedia
Next I have predefined some numbers for orientation.
| rezolution -> | 1\4 ≈ | 1\8 ≈ | 1\16 ≈ | 1\32 ≈ | 1\64 ≈ |
|---|---|---|---|---|---|
| ↓ memory space | ±0.25 | ±0.125 | ±0.062 | ±0.031 | ±0.015 |
| 8 bytes | Q(5.2 ) | Q(4.3 ) | Q(3.4 ) | Q(2.5 ) | Q(1.6 ) |
| 16 bytes | Q(13.2 ) | Q(12.3 ) | Q(11.4 ) | Q(10.5 ) | Q(9.6 ) |
| 32 bytes | Q(29.2 ) | Q(28.3 ) | Q(27.4 ) | Q(26.5 ) | Q(25.6 ) |
| 64 bytes | Q(61.2 ) | Q(60.3 ) | Q(59.4 ) | Q(58.5 ) | Q(56.6 ) |
| 128 bytes | Q(125.2) | Q(124.3) | Q(123.4) | Q(122.5) | Q(121.6) |
Note: r ≈ is the approximate resolution.
A very large number with high resolution on 64 bit:
Q(50.12)
A number on 32 bit with resolution = 0.0005:
Q(20.11)
Q(14.17)
Bee is using default Q type for type inference, when precision is not specified. Default Q number has precision 10⁻⁵ = 2⁻¹⁷ ≈ 0.00001 and occupy 32 bit. It's a relative small number. For larger numbers you must specify the resolution and capacity.
Rational numbers and other numbers can be compared using "≈" instead of "=". Bee can be used to make aproximative computations and logic expressions based on precision.
In next example b = 0.33(3), delta = (b - a) = 0.083
** override default precision
set $precision := 0.01;
rule main:
new a := 0.25; -- real
new b := 1\3; -- rational O.33(3)
** using specified precision 0.01
print (a ≈ b); -- 0B0: (False, 0.033 - 0.25 = 0.08 )
** using specified precision:
print (a ≈ b ± 0.01); -- 0B0 (False)
print (a ≈ b ± 0.05); -- 0B0 (False)
print (a ≈ b ± 0.10); -- 0B1 (True)
return
Rational numbers are similar to complex numbers. The calculation of rational number is postponed until is necesary in expressions and it can produce different results depending on the precision.
** execute conversion
rule main:
new a := 0.25; -- real
new b := 1\4; -- rational
** explicit conversion R :> Q
expect a ≠ b; -- not equal, type mismatch
expect a ≈ b; -- values match, aproximation
expect a ≡ b; -- implicit conversion, match
** explicit conversion R :> Q
new c := a :> Q;
expect c = b; -- type & value match
expect c ≡ b; -- type & value match
** implicit conversion Q :> R
new r := c ∈ R;
expect c = 0.25;
return
Read next: Control


Affordance
The purpose of this site is to demonstrate the functionality of the js library. It does this splendidly by highlighting the code samples from the rest of the text and formatting them to optimally display the demo code.
This link does not look like a link. That's lame. I can't click on something that is not different enough to attract my attention.
Chunking
Different websites feeds are well seperated and more space is afforded to websites that deliver visual content.
There is very little visual seperation between the article and the rest of the website. It's very hard to know what to focus on.
Hick's Law
Evan's site has 3 navigational options, beautifully, stupidly simple.
So. Many. Options. Where am I going? How do I learn this? I am confused and intimitdated.
Signal-to-Noise Ratio
Nothing but content, no ads or distractions.
What am I supposed to be looking at, whats going on? What's important? So noisy.
Modularity
You can pull it off of youtube and embed it into any site and it still looks and functions great.
This page is artfully bad. Its elements are so intermingled, absolutely nothing about this is modular or reusable.


---
active_crumb: Pizzeria ex
layout: documentation
id: pizzeria
fa_icon: fa-cube
---
This example provides a simple pizza ordering model. It demonstrates how to work with dialogue systems which require confirmation logic.
Complexity:
Source code: GitHub
Review: All Examples at GitHub
You can create new Scala projects in many ways - we'll use SBT
to accomplish this task. Make sure that build.sbt
file has the following content:
ThisBuild / version := "0.1.0-SNAPSHOT" ThisBuild / scalaVersion := "3.2.2" lazy val root = (project in file(".")) .settings( name := "NLPCraft Pizzeria Example", version := "{{site.latest_version}}", libraryDependencies += "org.apache.nlpcraft" % "nlpcraft" % "{{site.latest_version}}", libraryDependencies += "org.apache.nlpcraft" % "nlpcraft-stanford" % "1.0.0", libraryDependencies += "edu.stanford.nlp" % "stanford-corenlp" % "4.5.1", libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.15" % "test" )
NOTE: use the latest versions of Scala, ScalaTest and StanfordNLP library.
Create the following files so that resulting project structure would look like the following:
pizzeria_model.yaml
- YAML configuration file which contains model description.PizzeriaModel.scala
- Model implementation.PizzeriaOrder.scala
- Pizza order state representation.PizzeriaModelPipeline.scala
- Model pipeline definition class.PizzeriaOrderMapper.scala
- {% scaladoc NCEntityMapper NCEntityMapper %} custom implementation.PizzeriaOrderValidator.scala
- {% scaladoc NCEntityValidator NCEntityValidator %} custom implementation.PizzeriaModelSpec.scala
- Test that allows to test your model.| build.sbt +--project | build.properties \--src +--main | +--resources | | pizzeria_model.yaml | \--scala | \--demo | \--components | PizzeriaModelPipeline.scala | PizzeriaOrderMapper.scala | PizzeriaOrderValidator.scala | PizzeriaModel.scala | PizzeriaOrder.scala \--test \--scala \--demo PizzeriaModelSpec.scala
We are going to start with declaring the static part of our model using YAML which we will later load
in our Scala-based model implementation.
Open src/main/resources/pizzeria_model.yaml
file and replace its content with the following YAML:
elements: - type: "ord:pizza" description: "Kinds of pizza." values: "margherita": [ ] "carbonara": [ ] "marinara": [ ] - type: "ord:pizza:size" description: "Size of pizza." values: "small": [ "{small|smallest|min|minimal|tiny} {size|piece|_}" ] "medium": [ "{medium|intermediate|normal|regular} {size|piece|_}" ] "large": [ "{big|biggest|large|max|maximum|huge|enormous} {size|piece|_}" ] - type: "ord:drink" description: "Kinds of drinks." values: "tea": [ ] "coffee": [ ] "cola": [ "{pepsi|sprite|dr. pepper|dr pepper|fanta|soda|cola|coca cola|cocacola|coca-cola}" ] - type: "ord:yes" description: "Confirmation (yes)." synonyms: - "{yes|yeah|right|fine|nice|excellent|good|correct|sure|ok|exact|exactly|agree}" - "{you are|_} {correct|right}" - type: "ord:no" description: "Confirmation (no)." synonyms: - "{no|nope|incorrect|wrong}" - "{you are|_} {not|are not|aren't} {correct|right}" - type: "ord:stop" description: "Stop and cancel all." synonyms: - "{stop|cancel|clear|interrupt|quit|close} {it|all|everything|_}" - type: "ord:status" description: "Order status information." synonyms: - "{present|current|_} {order|_} {status|state|info|information}" - "what {already|_} ordered" - type: "ord:finish" description: "The order is over." synonyms: - "{i|everything|order|_} {be|_} {finish|ready|done|over|confirmed}" - type: "ord:menu" description: "Order menu." synonyms: - "{menu|carte|card}" - "{products|goods|food|item|_} list" - "{hi|help|hallo}"
Lines 2, 9, 16
define order elements which present parts of order.
Lines 35, 40, 46, 51
define command elements which are used to control order state.
Lines 23, 29
define elements which are used for commands confirmation or cancellation.
YAML vs. API
As usual, this YAML-based static model definition is convenient but totally optional. All elements definitions
can be provided programmatically inside Scala model PizzeriaModel
class as well.
Open src/main/scala/demo/PizzeriaOrder.scala
file and replace its content with the following code:
package demo import scala.collection.mutable import org.apache.nlpcraft.* enum PizzeriaOrderState: case DIALOG_EMPTY, DIALOG_IS_READY, DIALOG_SHOULD_CANCEL, DIALOG_SPECIFY, DIALOG_CONFIRM private object OrderPosition: val DFLT_QTY = 1 private trait OrderPosition: val name: String var qty: Option[Int] require(name != null && name.nonEmpty) case class Pizza(name: String, var size: Option[String], var qty: Option[Int]) extends OrderPosition: override def toString = s"$name '${size.getOrElse("undefined size")}' ${qty.getOrElse(OrderPosition.DFLT_QTY)} pcs" case class Drink(name: String, var qty: Option[Int]) extends OrderPosition: override def toString = s"$name ${qty.getOrElse(OrderPosition.DFLT_QTY)} pcs" import PizzeriaOrderState.* class PizzeriaOrder: private var state = DIALOG_EMPTY private val pizzas = mutable.ArrayBuffer.empty[Pizza] private val drinks = mutable.ArrayBuffer.empty[Drink] def isEmpty: Boolean = pizzas.isEmpty && drinks.isEmpty def isValid: Boolean = !isEmpty && findPizzaWithoutSize.isEmpty def add(ps: Seq[Pizza], ds: Seq[Drink]): Unit = def setByName[T <: OrderPosition](buf: mutable.ArrayBuffer[T], t: T): Unit = buf.find(_.name == t.name) match case Some(foundT) => if t.qty.nonEmpty then foundT.qty = t.qty case None => buf += t for (p <- ps) def setPizza(pred: Pizza => Boolean, notFound: => () => Unit): Unit = pizzas.find(pred) match case Some(foundPizza) => if p.size.nonEmpty then foundPizza.size = p.size if p.qty.nonEmpty then foundPizza.qty = p.qty case None => notFound() if p.size.nonEmpty then setPizza( x => x.name == p.name && x.size == p.size, () => setPizza(x => x.name == p.name && x.size.isEmpty, () => pizzas += p) ) else setByName(pizzas, p) for (d <- ds) setByName(drinks, d) def findPizzaWithoutSize: Option[Pizza] = pizzas.find(_.size.isEmpty) def fixPizzaWithoutSize(size: String): Boolean = findPizzaWithoutSize match case Some(p) => p.size = Option(size) true case None => false def getState: PizzeriaOrderState = state def setState(state: PizzeriaOrderState): Unit = this.state = state override def toString: String = if !isEmpty then val ps = if pizzas.nonEmpty then s"pizza: ${pizzas.mkString(", ")}" else "" val ds = if drinks.nonEmpty then s"drinks: ${drinks.mkString(", ")}" else "" if ds.isEmpty then ps else if ps.isEmpty then ds else s"$ps, $ds" else "nothing ordered"
Line 6
defines order states enumeration.
Lines 17 and 20
define order parts classes definition.
Line 25
defines pizza order state representation.
Open src/main/scala/demo/PizzeriaModel.scala
file and replace its content with the following code:
package demo import com.typesafe.scalalogging.LazyLogging import org.apache.nlpcraft.* import org.apache.nlpcraft.NCResultType.* import org.apache.nlpcraft.annotations.* import demo.{PizzeriaOrder as Order, PizzeriaOrderState as State} import demo.PizzeriaOrderState.* import demo.components.PizzeriaModelPipeline import org.apache.nlpcraft.nlp.* object PizzeriaExtractors: def extractPizzaSize(e: NCEntity): String = e[String]("ord:pizza:size:value") def extractQty(e: NCEntity, qty: String): Option[Int] = Option.when(e.contains(qty))(e[String](qty).toDouble.toInt) def extractPizza(e: NCEntity): Pizza = Pizza( e[String]("ord:pizza:value"), e.get[String]("ord:pizza:size"), extractQty(e, "ord:pizza:qty") ) def extractDrink(e: NCEntity): Drink = Drink(e[String]("ord:drink:value"), extractQty(e, "ord:drink:qty")) import PizzeriaExtractors.* object PizzeriaModel extends LazyLogging: type Result = (NCResult, State) private val UNEXPECTED_REQUEST = new NCRejection("Unexpected request for current dialog context.") private def getCurrentOrder()(using ctx: NCContext): Order = val sess = ctx.getConversation.getData val usrId = ctx.getRequest.getUserId sess.get[Order](usrId) match case Some(ord) => ord case None => val ord = new Order() sess.put(usrId, ord) ord private def mkResult(msg: String): NCResult = NCResult(msg, ASK_RESULT) private def mkDialog(msg: String): NCResult = NCResult(msg, ASK_DIALOG) private def doRequest(body: Order => Result)(using ctx: NCContext, im: NCIntentMatch): NCResult = val o = getCurrentOrder() logger.info(s"Intent '${im.getIntentId}' activated for text: '${ctx.getRequest.getText}'.") logger.info(s"Before call [desc=${o.getState.toString}, resState: $o.") val (res, resState) = body.apply(o) o.setState(resState) logger.info(s"After call [desc=$o, resState: $resState.") res private def askIsReady(): Result = mkDialog("Is order ready?") -> DIALOG_IS_READY private def askSpecify(o: Order): Result = require(!o.isValid) o.findPizzaWithoutSize match case Some(p) => mkDialog(s"Choose size (large, medium or small) for: '${p.name}'") -> DIALOG_SPECIFY case None => require(o.isEmpty) mkDialog("Please order something. Ask `menu` to look what you can order.") -> DIALOG_SPECIFY private def askShouldStop(): Result = mkDialog("Should current order be canceled?") -> DIALOG_SHOULD_CANCEL private def doShowMenuResult(): NCResult = mkResult( "There are accessible for order: margherita, carbonara and marinara. " + "Sizes: large, medium or small. " + "Also there are tea, coffee and cola." ) private def doShowMenu(state: State): Result = doShowMenuResult() -> state private def doShowStatus(o: Order, state: State): Result = mkResult(s"Current order state: $o.") -> state private def askConfirm(o: Order): Result = require(o.isValid) mkDialog(s"Let's specify your order: $o. Is it correct?") -> DIALOG_CONFIRM private def doResultWithClear(msg: String)(using ctx: NCContext, im: NCIntentMatch): Result = val conv = ctx.getConversation conv.getData.remove(ctx.getRequest.getUserId) conv.clearStm(_ => true) conv.clearDialog(_ => true) mkResult(msg) -> DIALOG_EMPTY private def doStop(o: Order)(using ctx: NCContext, im: NCIntentMatch): Result = doResultWithClear( if !o.isEmpty then "Everything cancelled. Ask `menu` to look what you can order." else "Nothing to cancel. Ask `menu` to look what you can order." ) private def doContinue(): Result = mkResult("OK, please continue.") -> DIALOG_EMPTY private def askConfirmOrAskSpecify(o: Order): Result = if o.isValid then askConfirm(o) else askSpecify(o) private def askIsReadyOrAskSpecify(o: Order): Result = if o.isValid then askIsReady() else askSpecify(o) private def askStopOrDoStop(o: Order)(using ctx: NCContext, im: NCIntentMatch): Result = if o.isValid then askShouldStop() else doStop(o) import PizzeriaModel.* class PizzeriaModel extends NCModel( NCModelConfig("nlpcraft.pizzeria.ex", "Pizzeria Example Model", "1.0"), PizzeriaModelPipeline.PIPELINE ) with LazyLogging: // This method is defined in class scope and has package access level for tests reasons. private[demo] def doExecute(o: Order)(using ctx: NCContext, im: NCIntentMatch): Result = require(o.isValid) doResultWithClear(s"Executed: $o.") private def doExecuteOrAskSpecify(o: Order)(using ctx: NCContext, im: NCIntentMatch): Result = if o.isValid then doExecute(o) else askSpecify(o) @NCIntent("intent=yes term(yes)={# == 'ord:yes'}") def onYes(using ctx: NCContext, im: NCIntentMatch): NCResult = doRequest( o => o.getState match case DIALOG_CONFIRM => doExecute(o) case DIALOG_SHOULD_CANCEL => doStop(o) case DIALOG_IS_READY => askConfirmOrAskSpecify(o) case DIALOG_SPECIFY | DIALOG_EMPTY => throw UNEXPECTED_REQUEST ) @NCIntent("intent=no term(no)={# == 'ord:no'}") def onNo(using ctx: NCContext, im: NCIntentMatch): NCResult = doRequest( o => o.getState match case DIALOG_CONFIRM | DIALOG_IS_READY => doContinue() case DIALOG_SHOULD_CANCEL => askConfirmOrAskSpecify(o) case DIALOG_SPECIFY | DIALOG_EMPTY => throw UNEXPECTED_REQUEST ) @NCIntent("intent=stop term(stop)={# == 'ord:stop'}") // It doesn't depend on order validity and dialog state. def onStop(using ctx: NCContext, im: NCIntentMatch): NCResult = doRequest(askStopOrDoStop) @NCIntent("intent=status term(status)={# == 'ord:status'}") def onStatus(using ctx: NCContext, im: NCIntentMatch): NCResult = doRequest( o => o.getState match // Ignore `status`, confirm again. case DIALOG_CONFIRM => askConfirm(o) // Changes state. case DIALOG_SHOULD_CANCEL => doShowStatus(o, DIALOG_EMPTY) // Keeps same state. case DIALOG_EMPTY | DIALOG_IS_READY | DIALOG_SPECIFY => doShowStatus(o, o.getState) ) @NCIntent("intent=finish term(finish)={# == 'ord:finish'}") def onFinish(using ctx: NCContext, im: NCIntentMatch): NCResult = doRequest( o => o.getState match // Like YES if valid. case DIALOG_CONFIRM => doExecuteOrAskSpecify(o) // Ignore `finish`, specify again. case DIALOG_SPECIFY => askSpecify(o) case DIALOG_EMPTY | DIALOG_IS_READY | DIALOG_SHOULD_CANCEL => askConfirmOrAskSpecify(o) ) @NCIntent("intent=menu term(menu)={# == 'ord:menu'}") // It doesn't depend and doesn't influence on order validity and dialog state. def onMenu(using ctx: NCContext, im: NCIntentMatch): NCResult = doRequest(o => doShowMenu(o.getState)) @NCIntent("intent=order term(ps)={# == 'ord:pizza'}* term(ds)={# == 'ord:drink'}*") def onOrder( using ctx: NCContext, im: NCIntentMatch, @NCIntentTerm("ps") ps: List[NCEntity], @NCIntentTerm("ds") ds: List[NCEntity] ): NCResult = doRequest( o => require(ps.nonEmpty || ds.nonEmpty); // It doesn't depend on order validity and dialog state. o.add(ps.map(extractPizza), ds.map(extractDrink)); askIsReadyOrAskSpecify(o) ) @NCIntent("intent=orderSpecify term(size)={# == 'ord:pizza:size'}") def onOrderSpecify( using ctx: NCContext, im: NCIntentMatch, @NCIntentTerm("size") size: NCEntity ): NCResult = doRequest( // If order in progress and has pizza with unknown size, it doesn't depend on dialog state. o => if !o.isEmpty && o.fixPizzaWithoutSize(extractPizzaSize(size)) then askIsReadyOrAskSpecify(o) else throw UNEXPECTED_REQUEST ) override def onRejection( using ctx: NCContext, im: Option[NCIntentMatch], e: NCRejection ): Option[NCResult] = if im.isEmpty || getCurrentOrder().isEmpty then throw e Option(doShowMenuResult())
There are a number of intents in the given model which allow to prepare, change, confirm and cancel pizza orders. Note that given test model works with only one single user. Let's review this implementation step by step:
Line 12
declares PizzeriaExtractors
helper object which provides
conversion methods from {% scaladoc NCEntity NCEntity %} objects and model data objects.
Line 27
defines PizzeriaModel
companion object which contains
static content and helper methods.
line 114
our class extends {% scaladoc NCModel NCModel %} with two mandatory parameters.
Line 115
creates model configuration with most default parameters.
Line 116
passes pipeline parameter which was prepared in PizzeriaModelPipeline
.
Lines 173 and 174
annotate intents order
and its callback method onOrder()
.
Intent order
requires lists of pizza and drinks for the order.
Note that at least one of these lists shouldn't be empty, otherwise intent is not triggered.
In its callback current order state is changed.
If processed order is in valid state user receives order confirmation request like "Is order ready?",
otherwise user receives request which asks him to specify the order.
Both responses have {% scaladoc NCResultType#ASK_DIALOG-0 ASK_DIALOG %} type.
order
intent.
Lines 187 and 188
annotate intents orderSpecify
and its callback method onOrderSpecify()
.
Intent orderSpecify
requires pizza size value parameter.
Callback checks that it was called just for suitable order state.
Current order state is changed and user receives order confirmation request like "Is order ready?" again.
Lines 126, 127 and 135, 136
annotate intents yes
and no
with related callbacks onYes()
and onNo()
.
These intents are expected after user answered on received confirmation requests.
Callbacks change order state, send another requests to user or reject these intents depending on current order state.
Lines 143 and 145, 147 and 148, 158 and 159, 168 and 170
annotate intents
stop
, status
, finish
and menu
intents
with related callbacks. They are order management commands, their actions are depended on current order state.
Line 201
annotates onRejection
method
which is called if there aren't any triggered intents.
Open src/main/scala/demo/components/PizzeriaOrderValidator.scala
file and replace its content with the following code:
package demo.components import org.apache.nlpcraft.* class PizzeriaOrderValidator extends NCEntityValidator: override def validate(req: NCRequest, cfg: NCModelConfig, ents: List[NCEntity]): Unit = def count(typ: String): Int = ents.count(_.getType == typ) val cntPizza = count("ord:pizza") val cntDrink = count("ord:drink") val cntNums = count("stanford:number") val cntSize = count("ord:pizza:size") // Single size - it is order specification request. if (cntSize != 1 && cntSize > cntPizza) || cntNums > cntPizza + cntDrink then throw new NCRejection("Invalid pizza request.")
PizzeriaOrderValidator
is implementation of {% scaladoc NCEntityValidator NCEntityValidator %}.
It is designed for validation order content that allows to reject invalid orders right away.
Open src/main/scala/demo/components/PizzeriaOrderMapper.scala
file and replace its content with the following code:
package demo.components import org.apache.nlpcraft.* import com.typesafe.scalalogging.LazyLogging import org.apache.nlpcraft.NCResultType.ASK_DIALOG import scala.collection.* case class PizzeriaOrderMapperDesc(elementType: String, propertyName: String) private object PizzeriaOrderMapper: extension(entity: NCEntity) private def position: Double = val toks = entity.getTokens (toks.head.getIndex + toks.last.getIndex) / 2.0 private def tokens: List[NCToken] = entity.getTokens private def str(es: Iterable[NCEntity]): String = es.map(e => s"type=${e.getType}(${e.tokens.map(_.getIndex).mkString("[", ",", "]")})").mkString("{", ", ", "}") def apply(extra: PizzeriaOrderMapperDesc, descr: PizzeriaOrderMapperDesc*): PizzeriaOrderMapper = new PizzeriaOrderMapper(extra, descr) import PizzeriaOrderMapper.* case class PizzeriaOrderMapper( extra: PizzeriaOrderMapperDesc, descr: Seq[PizzeriaOrderMapperDesc] ) extends NCEntityMapper with LazyLogging: override def map(req: NCRequest, cfg: NCModelConfig, ents: List[NCEntity]): List[NCEntity] = def map(destEnt: NCEntity, destProp: String, extraEnt: NCEntity): NCEntity = new NCPropertyMapAdapter with NCEntity: destEnt.keysSet.foreach(k => put(k, destEnt(k))) put[String](destProp, extraEnt[String](extra.propertyName).toLowerCase) override val getTokens: List[NCToken] = (destEnt.tokens ++ extraEnt.tokens).sortBy(_.getIndex) override val getRequestId: String = req.getRequestId override val getType: String = destEnt.getType val descrMap = descr.map(p => p.elementType -> p).toMap val destEnts = mutable.HashSet.empty ++ ents.filter(e => descrMap.contains(e.getType)) val extraEnts = ents.filter(_.getType == extra.elementType) if destEnts.nonEmpty && extraEnts.nonEmpty && destEnts.size >= extraEnts.size then val used = (destEnts ++ extraEnts).toSet val dest2Extra = mutable.HashMap.empty[NCEntity, NCEntity] for (extraEnt <- extraEnts) val destEnt = destEnts.minBy(m => Math.abs(m.position - extraEnt.position)) destEnts -= destEnt dest2Extra += destEnt -> extraEnt val unrelated = ents.filter(e => !used.contains(e)) val artificial = for ((m, e) <- dest2Extra) yield map(m, descrMap(m.getType).propertyName, e) val unused = destEnts val res = (unrelated ++ artificial ++ unused).sortBy(_.tokens.head.getIndex) logger.debug(s"Elements mapped [input=${str(ents)}, output=${str(res)}]") res else ents
PizzeriaOrderMapper
is implementation of {% scaladoc NCEntityMapper NCEntityMapper %}.
It is designed for complex compound entities building based on another entities.
Line 11
defines PizzeriaOrderMapper
model companion object which contains
helper methods.
Line 26
defines PizzeriaOrderMapper
model which implements {% scaladoc NCEntityMapper NCEntityMapper %}.
Line 30
defines helper method
{% scaladoc NCEntityMapper#map-fffff77c map() %} w
hich clones destEn
entity,
extends it by extraEnt
tokens and destProp
property and, as result,
returns new entities instances instead of passed into the method.
Line 60
defines PizzeriaOrderMapper
result.
These entities will be processed further instead of passed into this component method.
Open src/main/scala/demo/components/PizzeriaModelPipeline.scala
file and replace its content with the following code:
package demo.components import edu.stanford.nlp.pipeline.StanfordCoreNLP import org.apache.nlpcraft.nlp.parsers.* import org.apache.nlpcraft.* import org.apache.nlpcraft.nlp.stemmer.* import org.apache.nlpcraft.nlp.enrichers.NCEnStopWordsTokenEnricher import org.apache.nlpcraft.nlp.parsers.NCSemanticEntityParser import org.apache.nlpcraft.nlp.stanford.* import java.util.Properties object PizzeriaModelPipeline: val PIPELINE: NCPipeline = val stanford = val props = new Properties() props.setProperty("annotators", "tokenize, ssplit, pos, lemma, ner") new StanfordCoreNLP(props) val tokParser = new NCStanfordNLPTokenParser(stanford) import demo.components.PizzeriaOrderMapperDesc as D new NCPipelineBuilder(). withTokenParser(tokParser). withTokenEnricher(new NCEnStopWordsTokenEnricher()). withEntityParser(new NCStanfordNLPEntityParser(stanford, Set("number"))). withEntityParser(new NCSemanticEntityParser(new NCEnStemmer, tokParser, "pizzeria_model.yaml")). withEntityMapper(PizzeriaOrderMapper( extra = D("ord:pizza:size", "ord:pizza:size:value"), descr = D("ord:pizza", "ord:pizza:size")) ). withEntityMapper(PizzeriaOrderMapper( extra = D("stanford:number", "stanford:number:nne"), descr = D("ord:pizza", "ord:pizza:qty"), D("ord:drink", "ord:drink:qty")) ). withEntityValidator(new PizzeriaOrderValidator()). build
There is model pipeline preparing place.
Line 14
defines the pipeline.
Line 27
declares {% scaladoc nlp/parsers/NCSemanticEntityParser NCSemanticEntityParser %}
which is based on YAM model definition pizzeria_model.yaml
.
Lines 28 and 32
define entity mappers PizzeriaOrderMapper
instances which
map ord:pizza
elements with theirs sizes from ord:pizza:size
and
quantities from stanford:number
.
Line 36
defines PizzeriaOrderValidator
class described above.
The test defined in PizzeriaModelSpec
allows to check that all input test sentences are
processed correctly and trigger the expected intents:
package demo import org.apache.nlpcraft.* import org.apache.nlpcraft.NCResultType.* import demo.PizzeriaModel.Result import demo.PizzeriaOrderState.* import org.scalatest.BeforeAndAfter import org.scalatest.funsuite.AnyFunSuite import scala.language.implicitConversions import scala.util.Using import scala.collection.mutable object PizzeriaModelSpec: type Request = (String, NCResultType) private class ModelTestWrapper extends PizzeriaModel: private var o: PizzeriaOrder = _ override def doExecute(o: PizzeriaOrder)(using ctx: NCContext, im: NCIntentMatch): Result = val res = super.doExecute(o) this.o = o res def getLastExecutedOrder: PizzeriaOrder = o def clearLastExecutedOrder(): Unit = o = null private class Builder: private val o = new PizzeriaOrder o.setState(DIALOG_EMPTY) def withPizza(name: String, size: String, qty: Int): Builder = o.add(Seq(Pizza(name, Some(size), Some(qty))), Seq.empty) this def withDrink(name: String, qty: Int): Builder = o.add(Seq.empty, Seq(Drink(name, Some(qty)))) this def build: PizzeriaOrder = o import PizzeriaModelSpec.* class PizzeriaModelSpec extends AnyFunSuite with BeforeAndAfter: private val mdl = new ModelTestWrapper() private val client = new NCModelClient(mdl) private val msgs = mutable.ArrayBuffer.empty[mutable.ArrayBuffer[String]] private val errs = mutable.HashMap.empty[Int, Throwable] private var testNum: Int = 0 after { if client != null then client.close() for ((seq, num) <- msgs.zipWithIndex) println("#" * 150) for (line <- seq) println(line) errs.get(num) match case Some(err) => err.printStackTrace() case None => // No-op. require(errs.isEmpty, s"There are ${errs.size} errors above.") } private def dialog(exp: PizzeriaOrder, reqs: Request*): Unit = val testMsgs = mutable.ArrayBuffer.empty[String] msgs += testMsgs testMsgs += s"Test: $testNum" for (((txt, expType), idx) <- reqs.zipWithIndex) try mdl.clearLastExecutedOrder() val resp = client.ask(txt, "userId") testMsgs += s">> Request: $txt" testMsgs += s">> Response: '${resp.getType}': ${resp.getBody}" if expType != resp.getType then errs += testNum -> new Exception(s"Unexpected result type [num=$testNum, txt=$txt, expected=$expType, type=${resp.getType}]") // Check execution result on last request. if idx == reqs.size - 1 then val lastOrder = mdl.getLastExecutedOrder def s(o: PizzeriaOrder) = if o == null then null else s"Order [state=${o.getState}, desc=$o]" val s1 = s(exp) val s2 = s(lastOrder) if s1 != s2 then errs += testNum -> new Exception( s"Unexpected result [num=$testNum, txt=$txt]" + s"\nExpected: $s1" + s"\nReal : $s2" ) catch case e: Exception => errs += testNum -> new Exception(s"Error during test [num=$testNum]", e) testNum += 1 test("test") { given Conversion[String, Request] with def apply(txt: String): Request = (txt, ASK_DIALOG) dialog( new Builder().withDrink("tea", 2).build, "Two tea", "yes", "yes" -> ASK_RESULT ) dialog( new Builder(). withPizza("carbonara", "large", 1). withPizza("marinara", "small", 1). withDrink("tea", 1). build, "I want to order carbonara, marinara and tea", "large size please", "smallest", "yes", "correct" -> ASK_RESULT ) dialog( new Builder().withPizza("carbonara", "small", 2).build, "carbonara two small", "yes", "yes" -> ASK_RESULT ) dialog( new Builder().withPizza("carbonara", "small", 1).build, "carbonara", "small", "yes", "yes" -> ASK_RESULT ) dialog( null, "marinara", "stop" -> ASK_RESULT ) dialog( new Builder(). withPizza("carbonara", "small", 2). withPizza("marinara", "large", 4). withDrink("cola", 3). withDrink("tea", 1). build, "3 cola", "one tea", "carbonara 2", "small", "4 marinara big size", "menu" -> ASK_RESULT, "done", "yes" -> ASK_RESULT ) dialog( new Builder(). withPizza("margherita", "small", 2). withPizza("marinara", "small", 1). withDrink("tea", 3). build, "margherita two, marinara and three tea", "small", "small", "yes", "yes" -> ASK_RESULT ) dialog( new Builder(). withPizza("margherita", "small", 2). withPizza("marinara", "large", 1). withDrink("cola", 3). build, "small margherita two, marinara big one and three cola", "yes", "yes" -> ASK_RESULT ) dialog( new Builder(). withPizza("margherita", "small", 1). withPizza("marinara", "large", 2). withDrink("coffee", 2). build, "small margherita, 2 marinara and 2 coffee", "large", "yes", "yes" -> ASK_RESULT ) }
PizzeriaModelSpec
is complex test which is designed as dialog with pizza ordering bot.
Line 14
declares PizzeriaModelSpec
test companion object which contains
static content and helper methods.
Line 48
defines after
block.
It closes model client and prints test results.
Line 61
defines test helper method dialog()
.
It sends request to model via client's method
{% scaladoc NCModelClient#ask-fffff9ce ask() %}
and accumulates execution results.
Line 96
defines main test block.
It contains user request descriptions and their expected results taking into account order state.
You can run this test via SBT task executeTests
or using IDE.
PS C:\apache\incubator-nlpcraft-examples\pizzeria> sbt executeTests
You've created pizza model and tested it.


--- layout: post title: Donkey Kong Jungle Beat date: 2005-01-05 00:00:00 categories: monkeys play ---
Nintendo build on the Donkey Konga drums with Donkey Kong Jungle Beat.
Over the Christmas period I was pleasantly surprised by how appealing Donkey Konga was to friends and family who don't normally go for computer games...


I recently graduated from the Web Development Immersive program at General Assembly where I studied full-stack JavaScript technologies such as Angular, Node, and jQuery, along with HTML and CSS. I pivoted from my fine arts background into web development after witnessing the impact of the internet on the fine art world. I am finding that skills that were valuable to me as an artist, such as process-oriented creative thinking, meticulousness, and the drive to see a project through from start to finish, are also valuable in the world of programming. I am now seeking a role where I can leverage my creative and technical skill sets within an organization that fosters continuous learning and growth.


Upload files
X
Having problems?Try the
basic uploader
+ Add more files
Options
Description
Advanced
Category
None
Notify by email
Nobody
Privacy
Everybody on project
Nobody
will be notified of this file upload
Send me a copy