Mobile robots typically use microphone arrays for recording its surrounding environment for real-time human operator listening.
These complex arrangements led to Robot Audition; the ability of a robot to listen to multiple sound sources at once(Nakadai et al., 2000, Okuno and Nakadai, 2015).
Minimum power consumption and real-time performance are vital system requirements in robotics, therefore microphone arrays are avoided due to their costly processing time(Keyrouz, 2011).
Tetrahedral microphones have been used for detection and tracking of UAVs by the Army Research Laboratory, Maryland USA. (Benyamin and Goldman, 2014).
Current systems do not integrate microphones capable of planar audio capture. Such microphones are known as ambisonic microphones.
Ambisonic Spatial Audio Parrot Jumping Sumo Audio Processing 3D camera Soldier Acoustic Robots


--- layout: single author_profile: true ---
It is evident that, with the sheer amount of discourse taking place on social media platforms, seemingly unbelievable misinformation can slip through the cracks of moderation and explode in popularity. Claims disputing the true lethality of the COVID-19 coronavirus or the validity of the 2020 election have taken sites like Twitter and Reddit by storm, prompting data science communities to analyze how such claims were conceived and spread. We attempt to explore how these kinds of claims spread, if at all, and compared these three different form of diffusion to each other."False information that is spread, regardless of whether there is intent to mislead."


Before Change
Base class for Amazon first-party Estimator implementations. This class isn"t intended
to be instantiated directly.
feature_dim = hp("feature_dim", (validation.isint, validation.gt(0)))
mini_batch_size = hp("mini_batch_size", (validation.isint, validation.gt(0)))
def __init__(self, role, train_instance_count, train_instance_type, data_location=None, **kwargs):
After Change
Base class for Amazon first-party Estimator implementations. This class isn"t intended
to be instantiated directly.
feature_dim = hp("feature_dim", validation.gt(0), data_type=int)
mini_batch_size = hp("mini_batch_size", validation.gt(0), data_type=int)
def __init__(self, role, train_instance_count, train_instance_type, data_location=None, **kwargs):


Find out everything you need to know about how to use this plugin on its demo page at http://dfcb.github.com/BigVideo.js.
If you’re using Bower (and you should be!) installing BigVideo and its dependencies is simply:
bower install BigVideo.js
This downloads and installs BigVideo to the bower_components
folder. Add to your page the usual way with script tags, or using RequireJS.
If you’d rather download things manually, you can grab the latest zip from that lovely button on the right (or this link). You will also need the dependencies:
If RequireJS is detected, BigVideo.js defines itself as an anonymous module. Require it as:
javascript
require(['path/to/bigvideo'], function(bigvideo) {
// do stuff here
});
Make sure your require config is set up correctly; an example configuration is as follows:
javascript
require.config({
paths: {
"BigVideo": "bower_components/BigVideo.js/lib/bigvideo",
"jquery": "bower_components/jquery/jquery",
"jquery-ui": "bower_components/jquery-ui/ui/jquery-ui",
"videojs": "bower_components/video.js/video",
"imagesloaded": "bower_components/imagesloaded/imagesloaded",
"eventEmitter/EventEmitter": "bower_components/eventEmitter/EventEmitter",
"eventie/eventie": "bower_components/eventie/eventie"
},
shim: {
"videojs": {exports: 'videojs'}
}
});
This is to ensure that BigVideo and all its dependencies get the right paths, and that RequireJS knows how to reference Video.js.
Follow @johnpolacek on Twitter
Thanks to Matt Brennan for Bower integration
We are the development group at Draftfcb Chicago. If you want to work on big digital ideas for big brands, get in touch with us at<EMAIL_ADDRESS>The MIT License (MIT) Copyright © 2012 John Polacek
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


FUN WITH
Static Site Tools
About SSGs
Intro to Hugo
Fun Content!
Movies
Hugos
Hi, I'M Hugo!
Getting Hugo
03
04
05
06
07
08
09
10


This Keyboard follows the Gurmukhi WinScript Keyboard Layout designed by NLCI in 1988. Several linguists and members of translation community are still using this keyboard layout for keyboarding the text. This is a phonetic based keyboarding system designed with the objective of keyboarding text with minimal keystrokes. Keys are also layed out according the frequency of occurance, yet tried to follow a phonetic based keyboarding system.
See the Pen Gurmukhi WinScript (NLCI) Keyman Keyboard Layout by binilasanki (@binila) on CodePen.
| Keys | Character |
|---|---|
| gg | ਗ਼ |
| ii | ਈ |
| jj | ਜ਼ |
| ll | ਲ਼ |
| KK | ਖ਼ |
| oo | ಓ |
| rr | ੜ |
| uu | ਊ |
| ss | ਸ਼ |
X is used as virama Eg k X L will generate ਕ੍ਲ਼
| Keys | Character |
|---|---|
| =r | ੜ |
| Keys | Character |
|---|---|
| ੀi | ੀ |
| ੂu | ੂ |
| ਾa | ਾ |
x is used as conjuncts Eg k x l will generate ਕ੍ਲ
` Backtick with number will get Gurumukhi number Eg ` 1 will generate ੧
` Backtick is used to change into English Eg ` ਤ will generate q


pyfea.fea.simulation¶
Simulation¶
Simulation class for defining a simulation including considered physics effects, and boundary conditions.
-
class
pyfea.fea.simulation.
Simulation
(assembly, physics_effects=[], webserver=False, sim_poll_freq=1)¶ Simulation class to run transient FEA of an assembly according to specified physics modules.
-
class
SimSpace
(q_in, q_out, **kwargs)¶ This should probably be a wrapper for a c++ module. EDIT: Probably not going to happen for a bit
-
__init__
(q_in, q_out, **kwargs)¶ Initialize self. See help(type(self)) for accurate signature.
-
calculate
(dt='auto')¶ Calculates the physical parameter with lowest timestep.
-
assembly
= None¶
-
last_run
= []¶
-
physics_effects
= []¶
-
sequence
= []¶
-
-
__init__
(assembly, physics_effects=[], webserver=False, sim_poll_freq=1)¶ Initialize self. See help(type(self)) for accurate signature.
-
cmd
(command, prnt=False)¶
-
get
(variable)¶
-
getvar
(variable)¶
-
plot
(sim_property, plotter=None, parts=None, cmap=None, **kwargs)¶
-
plot_gif
(sim_property, filename, dt=0.5, t=20, **kwargs)¶
-
plot_rt
(sim_property, plotter=None, dt=0.5, t=None, update_scale=True, **kwargs)¶
-
run
(dt=None, t=None)¶
-
run_single_thread
(dt=None, t=None)¶
-
set_boundary_conditions
(**kwargs)¶
-
stop
()¶
-
update_database
()¶
-
assembly
= None¶
-
boundary_conditions
= {}¶
-
data_file
= None¶
-
parameters
= {}¶
-
physics_effects
= []¶
-
running
= False¶
-
sqlite_engine
= None¶
-
class
Physics_Effect_Base¶
Base class for defining physics effects
-
class
pyfea.fea.simulation.
Physics_Effect_Base
(simulation, **kwargs)¶ A class to set interfaces between the simulation and extensions for multiphysics calculations.
-
__init__
(simulation, **kwargs)¶ Initialize self. See help(type(self)) for accurate signature.
-
calculate
()¶ This is where the matrix calculations are done
-
classmethod
define_variables
(simulation)¶ Creates columns in the variable dataframe for data.
-
initvar
= {}¶
-
materialprops
= []¶
-
simulation
= None¶
-
testvar
= 'test'¶
-
variables
= []¶
-


A video of a puppy playing in the snow.
Next, we are going to listen to Baldr Sky Music.
This audio cannot be played because your browser does not support its format.


CloudFoundry - Service communications
Domain communication
Order by
-
name
domain
frequency
Communication information
Source domain:
Source service:
Destination domain:
Destination service:
Close


{% extends "default.html" %} {% block title %}
Too Long; Didn't Read: https://github.com/imakin/Inspense
So the needs of the daily money expense tracker is already bugging me for years. At those times i wrote my own python cli based app for that which runs on my linux, it is one of those my personal assistants relying on my Guake.
In late 2014 after finishing my bachelor study, i realized the need of GPS to accompany me traveling outside the town, further than my previous travels. So i bought myself an Android smartphone, for the sake of the GPS & map navigation. (yoi, my first smartphone, at the age of 22)
In early 2015, after moving to work in Banten i found a good application to do that in Android PlayStore: Income and Expense Insight which i used to use a lot.
Some people might said, it would be just the same as common accounting: input data so that incomes equal expenses. But let's keep the simplicity of the application which aimed for daily simple transaction: in every data of transaction, the income & expense flows to a single account: the so-called Base account The next simplicity is that the autogenerated reference number, which the user does not have to bother seing it, nor writing it himself. All s/he need to write is description, which is not even mandatory!
{% endblock %}


Before Change
with self.temporary_workdir() as workdir:
prep_commands_specs = self._emit_targets(workdir)
// Make sure the emitted BUILD under .pants.d is not ignored.
config = {"GLOBAL": {"build_ignore": [], "pants_ignore": []}}
pants_run = self.run_pants_with_workdir(
[goal] + prep_commands_specs, workdir, config=config
)
After Change
@contextmanager
def _execute_pants(self, goal):
with temporary_dir(os.getcwd()) as buildroot, self.temporary_workdir(buildroot) as workdir:
prep_commands_specs = self._emit_targets(buildroot)
pants_run = self.run_pants_with_workdir([goal] + prep_commands_specs, workdir)
self.assert_success(pants_run)
yield buildroot
def test_prep_command_in_compile(self):
with self._execute_pants("compile") as buildroot:
self._assert_goal_ran(buildroot, "compile")
self._assert_goal_did_not_run(buildroot, "test")


7/9 email
To Sign Petition, Use this Link
CSI Students, we deserve better.
Our class sizes are increasing, our professors are losing their jobs, and the quality of our education is at risk.
On June 30, 2020, thousands of CUNY employees were laid off amid serious budget cuts. At the College of Staten Island, low-paid adjunct faculty and college assistants have faced the brunt of the layoffs–without much notice.
What does this mean for us?
Having fewer teachers means having fewer courses offered and larger class sizes. It means losing trusted mentors and advisors. This dramatically increases the burden on those faculty remaining, both full-time and part-time.
These trends would forecast a continual decrease in enrollment, meaning CSI’s budgetary issues will only get worse. As a result, our choices will be diminished and the quality of our learning will suffer.
Budget cuts and layoffs targeting the most vulnerable employees are unnecessary. To date, neither CUNY’s nor CSI’s central administration has shared detailed budget information showing that these measures are necessary.
CUNY has already laid off nearly 3,000 employees, 422 of whom will lose their health insurance, despite the fact that CUNY received $251 million under the CARES Act.
Faculty and staff are undoubtedly the backbone of education at CSI, the ONLY public institution of higher education in the borough.
They bring their passion for teaching and guidance into our lives with little in return.
They are not dispensable, yet, the college’s actions show otherwise.
We, the undersigned, demand that CUNY does not lay off any part-time faculty due to COVID-19 or budgetary issues because it will unduly burden students.
We, the undersigned, demand that class sizes are not increased.
We, the undersigned, demand that our fellow students’ tuitions do not increase because of CUNY’s circumstances.
To protect CUNY is to protect students and the future of New York City.
To sign the petition, input your first and last name, as well as your email address.


--- # Feel free to add content and custom Front Matter to this file. # To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults #layout: home layout: landing ---
A hand-selected group of experts. Rigorously trained and brilliant to work with.
The turntabl learning program is legendary. All our developers pass through two months of tuition, group work and practical exercises.
Communication is key. Everyone in our team is an excellent communicator: a native English speaker with fantastic technical literacy.
We've been in the trenches. turntabl teams are led by experts. Agile development, program management, incident response: you can trust us.


About
Help & more info
The service is designed to be self-explanatory: on the home page you can perform two separate actions, viz., find the n-th prime number, and obtain the prime factorisation of a number. If you want to know more about the underlying mathematical concept, consult the articles on prime numbers and on prime factorisation.
If you want to know more about the underlying method—it is slightly tweaked trial division.
About
This website and the underlying service was created by s143364@TU/e for Assignment 2 for the course 2ID60 Web Technology, Q2 2015–2016. Enjoy!


My Favourite things.
My hobbies
Gaming
hand art e.g drawing, beading
swimming
My skills
Drawing
Coding
Creative writing
These are my favourite sites
you can
click
on a site to view.
google
w3schools
kahoot game


So much trouble just to have a functioning pretty historically accurate 10th century bow. Well, if I hadn't twisted it, nor shot arrows that were too light, it most likely would've been fine...


JavaScript is disabled on your browser.
Skip navigation links
Overview
Package
Class
Tree
Deprecated
Index
Help
Prev Letter
Next Letter
Frames
No Frames
All Classes
A
C
D
E
F
G
H
I
J
L
M
O
P
S
T
U
V
G
GameFragment
- Class in
edu.cnm.deepdive.java_learn.view
This class is used to give a common super class to all of the game types for modularity in the code.
GameFragment()
- Constructor for class edu.cnm.deepdive.java_learn.view.
GameFragment
getAccount()
- Method in class edu.cnm.deepdive.java_learn.service.
JavaLearnApplication
Gets account.
getAnswers()
- Method in class edu.cnm.deepdive.java_learn.model.pojo.
MultipleChoiceQWithA
getClient()
- Method in class edu.cnm.deepdive.java_learn.service.
JavaLearnApplication
Gets client.
getDDAnswerDao()
- Method in class edu.cnm.deepdive.java_learn.model.db.
JavaLearnDB
getDDQuestionDao()
- Method in class edu.cnm.deepdive.java_learn.model.db.
JavaLearnDB
getDefAnswer()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
DefinitionsAnswer
getDefAnswerId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
DefinitionsAnswer
getDefQuestion()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
DefinitionsQuestion
getDefQuestionId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
DefinitionsAnswer
getDefQuestionId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
DefinitionsQuestion
getFbAnswer()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
FillBlankAnswer
getFBAnswerDao()
- Method in class edu.cnm.deepdive.java_learn.model.db.
JavaLearnDB
getFbAnswerId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
FillBlankAnswer
getFBQuestionDao()
- Method in class edu.cnm.deepdive.java_learn.model.db.
JavaLearnDB
getFbQuestionId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
FillBlankAnswer
getFbQuestionId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
FillBlankQuestion
getHlAnswer()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
HighlightAnswer
getHLAnswerDao()
- Method in class edu.cnm.deepdive.java_learn.model.db.
JavaLearnDB
getHlAnswerId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
HighlightAnswer
getHlQuestion()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
HighlightQuestion
getHLQuestionDao()
- Method in class edu.cnm.deepdive.java_learn.model.db.
JavaLearnDB
getHlQuestionId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
HighlightAnswer
getHlQuestionId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
HighlightQuestion
getInstance(Context)
- Static method in class edu.cnm.deepdive.java_learn.model.db.
JavaLearnDB
getInstance()
- Static method in class edu.cnm.deepdive.java_learn.service.
JavaLearnApplication
Gets instance.
getLevel()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
Level
getLevelDao()
- Method in class edu.cnm.deepdive.java_learn.model.db.
JavaLearnDB
getLevelId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
DefinitionsQuestion
getLevelId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
FillBlankQuestion
getLevelId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
HighlightQuestion
getLevelId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
Level
getLevelId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
MultipleChoiceQuestion
getLevels()
- Method in class edu.cnm.deepdive.java_learn.model.pojo.
ProgressPojo
getMcAnswer()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
MultipleChoiceAnswer
getMCAnswerDao()
- Method in class edu.cnm.deepdive.java_learn.model.db.
JavaLearnDB
getMcAnswerId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
MultipleChoiceAnswer
getMcQuestion()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
MultipleChoiceQuestion
getMCQuestionDao()
- Method in class edu.cnm.deepdive.java_learn.model.db.
JavaLearnDB
getMcQuestionId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
MultipleChoiceAnswer
getMcQuestionId()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
MultipleChoiceQuestion
getQuestion()
- Method in class edu.cnm.deepdive.java_learn.model.pojo.
MultipleChoiceQWithA
getScore()
- Method in class edu.cnm.deepdive.java_learn.model.pojo.
ProgressPojo
getType()
- Method in class edu.cnm.deepdive.java_learn.model.entity.
HighlightAnswer
getUsername()
- Method in class edu.cnm.deepdive.java_learn.model.pojo.
UserPojo
getUuid()
- Method in class edu.cnm.deepdive.java_learn.model.pojo.
UserPojo
googleSignOut()
- Method in class edu.cnm.deepdive.java_learn.controller.
MainActivity
Method called when the user would like to log out, or when the initial login fails.
googleSignOut()
- Method in class edu.cnm.deepdive.java_learn.view.
HomeFragment
Google sign out.
A
C
D
E
F
G
H
I
J
L
M
O
P
S
T
U
V
Skip navigation links
Overview
Package
Class
Tree
Deprecated
Index
Help
Prev Letter
Next Letter
Frames
No Frames
All Classes


My career objective is to become a successful professional by utilizing my skills and enable further personal and professional development and work towards the prosperity of the organization.
CGPA: 7.8 *Till 7th Semester
Percentage: 86%
CGPA: 8.4
Project Title: Corrosion Prevention and Control Program on airframe structure of Antonov An-32
To analyse flow characteristics of different fixed wing monoplane configuration and show the best suitable position for the placement of wing on the fuselage for the selected airfoil.
Space debris is a big problem that will only get worse with time. Space Junk is beginning to litter space and satellites can potentially fail from collision with debris. Purpose is to innovate solutions to capture space debris. We come up with a solution by developing a design of a model (using concept of electromagnet). We reached up to Phase A ideation.
Drafting and Annotation using command prompt.
CAD design and kinematic simulaton.
basic 2D and 3D structural and Thermal analysis Using Concept of FEM and motion of fluid around objects as well as fluid behaviour in complex circulatory by fluid analysis.


If you have been alert, you may have noticed that when you defeat monster, you gain SP along with experience. SP stands for 'skill points'. If you are curious about SP, click the Character Status button and view the Status tab on the window. You must expend SP for each individual skill you acquire.
Tell me more about learning skills
Which skills ahould I learn first?
Return


| Math::Random::ISAAC::XS - C implementation of the ISAAC PRNG algorithm |
Math::Random::ISAAC::XS - C implementation of the ISAAC PRNG algorithm
version 1.004
This module implements the same interface as Math::Random::ISAAC
and can
be used as a drop-in replacement. This is the recommended implementation of
the module, based on Bob Jenkins' reference implementation in C.
Selecting the backend to use manually really only has two uses:
If you are trying to avoid the small overhead incurred with dispatching method calls to the appropriate backend modules.
If you are testing the module for performance and wish to explicitly decide which module you would like to use.
Example code:
# With Math::Random::ISAAC my $rng = Math::Random::ISAAC->new(time); my $rand = $rng->rand();
# With Math::Random::ISAAC::XS my $rng = Math::Random::ISAAC::XS->new(time); my $rand = $rng->rand();
See the Math::Random::ISAAC manpage for the full description.
Math::Random::ISAAC::XS->new( @seeds )
Implements the interface as specified in Math::Random::ISAAC
$rng->rand()
Implements the interface as specified in Math::Random::ISAAC
$rng->irand()
Implements the interface as specified in Math::Random::ISAAC
the Math::Random::ISAAC manpage
1;
Please report any bugs or feature requests on the bugtracker website http://rt.cpan.org/NoAuth/Bugs.html?Dist=Math-Random-ISAAC-XS
When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.
Jonathan Yu<EMAIL_ADDRESS>Legally speaking, this package and its contents are:
Copyright (c) 2011 by Jonathan Yu<EMAIL_ADDRESS>But this is really just a legal technicality that allows the author to offer this package under the public domain and also a variety of licensing options. For all intents and purposes, this is public domain software, which means you can do whatever you want with it.
The software is provided "AS IS", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.
| Math::Random::ISAAC::XS - C implementation of the ISAAC PRNG algorithm |


All files
<<<<<<< HEAD
58.97%
Statements
23/39
51.85%
Branches
14/27
70%
Functions
7/10
62.16%
Lines
23/37
=======
48.57%
Statements
17/35
36.84%
Branches
7/19
50%
Functions
5/10
48.48%
Lines
16/33
>>>>>>> 9aaab29cad941474edfc4d2f08f64884df26f8f2
File
Statements
Branches
Functions
Lines
<<<<<<< HEAD
hlv.js
58.97%
23/39
51.85%
14/27
70%
7/10
62.16%
23/37
=======
hype5.js
48.57%
17/35
36.84%
7/19
50%
5/10
48.48%
16/33
>>>>>>> 9aaab29cad941474edfc4d2f08f64884df26f8f2


Allow me to introduce myself I am Daniel, a structural engineer, database specialties thriving to become a web developer. As a Full-stack developer i am able to help clients interact and visualize thier web browsers using web applications. I graduated in Structural engineer 2012 and had my own construction company. I loved engineering but in recent years, I developed an interest for web development and has been working hard to grab an opportunity to pursue my newly discovered passion. Even though I have earned a certification in Database Specialists, I have always had an interest in software development at the back of my mind especially when it comes to cloud computing. I have had an in depth exposure to Mule Soft and API Integration systems and It was fascinating. I decided to build my set of skills in web development and database management for an ideal knowledge to pursue cloud computing services. My goal is to have an ample experience in finance, business and governmental sectors to enhance my portfolio. In the long run, I see myself acquiring enough experience to have my own company where I can have an independent contracts nationally and internationally. "It is never too late to be what you might have been." —George Eliot


Welcome to OnTrack! Here you can view your upcoming
appointments, book new appointments, hold zoom sessions with your GP, track COVID-19 cases in your area, and
get up-to-date information about restrictions in your local area.
Enter your postcode to find out about local
COVID-19 restrictions in your area.


Create a Profile
Are you a Designer? Developer? Put yourself out there so that others can find you!
SIGN UP NOWHave a great idea for a product, but need help making it a reality? We're here to help. Startup Matchmaker is the best place for designers and developers to find each other.
CREATE A PROFILEAre you a Designer? Developer? Put yourself out there so that others can find you!
SIGN UP NOWLooking for a fantastic developer to work with on the next big thing? Look no further.
START YOUR SEARCHNeed someone who can make a product intuitive and appealing? Get ready?
START YOUR SEARCH


Attacking From the Back of a Napkin
Help Me Pick New Logo Through 3 April 2016!
I am in the process of running a logo design contest on 99designs and have created a poll with 6 of the best logo designs I've received. I would love for you to vote on the logo design. It only takes a minute.
Like Sci-Fi? Read My New Online Fiction Series.
Do you like Sci-Fi? While I finish up my next novel, I have started an online fiction series called Forbearance. Picking up from the canteen scene in Bellicose, we meet Keius Minjen, a postal marine, as he tries to survive the battle planet Guna to exact revenge and one day liberate his homeland.
Sign-up if you want me to send you news about upcoming installments of Forbearance or my other writings.
This article discusses how to run a fairly efficient attack without relying on a battle calculator (link to a few battle calculators). The first section describes how to attack in waves. The second section provides a couple rules of thumb that help calculate how many units to bring.
Beyond the rule-of-thumb approach highlighted below, you can always manually calculate your attack. First, calculate the total power of both sides. When calculating the value of base defenses, remember to multiply the power by the number of turrets or rings (those multiples of five). Adjust for the presence of Command Centers to the appropriate party.
Attack in Waves
First, you should always consider attacking in waves. Never hurry an attack if you can avoid it. The great thing about being in the attack is that initiative should be yours. Therefore, you should time the attack to advantage you—so take your time. If you’re on the defense, then it is more likely you are being attacked by overwhelming force. Better to retreat and batter elsewhere than be battered by an attacker.
Figther Waves
The first waves should be massive Fighter drops. The goal is to kill all the support fleet (i.e., unshielded fleet) in one go. How many Fighters you bring should be based on the rule of thumb listed below. If the first wave was insufficient to waste all but a handful of support ships, then launch a second wave of Figthers to finish the job.
Heavy Bomber Waves
Once the Fighters have killed all but a few unshielded units, time to mop up with Heavy Bombers and other escort-killing units. If you read about Small Fleet Doctrine, you will know that Fighters are efficient against all unshielded units. Now that your Fighter drop has eliminated hostile Fighters, its time to focus on the Escort Ships.
The Small Fleet Doctrine says that Cruisers are efficient against all Escort Ships. However, Heavy Bombers, Destroyers and Frigates are fairly efficient against Cruisers and Heavy Cruisers. So, use the rule of thumb below to estimate how many you will need to wipe out your enemy’s Cruisers and Heavy Cruisers. As with Fighter waves, you may have under-estimated how many you need. Hit the enemy with a second HB wave until there are only BBs and up.
Escort Waves
By now, you should have removed all units below Battleships. If there are no Titans or larger in the remaining enemy fleet, use Cruisers with Fighters. The Fighters absorb some of the damage that would otherwise be directed at Cruisers. If there are Titans and larger, bring Heavy Cruisers.
Rules of Thumb
This section provides a few assumptions when planning your attack. Remember that these rules of thumb are just dirty-math assumptions. They vary with differing tech levels.
With FT and HB drops, you do not want to over-estimate the numbers you use. Those extra units will attack higher-shielded units that are unscathed by these units. That ruins your combat ratio. Remember, an attack with good ratios is like fine surgery.
Fighter Drops Use the ½/4/6 Rule
The 1 / 2 / 4 / 6 Rule provides a guide for how many Fighters you need to cleanse your enemy’s fleet of escort units. The numbers represent the following assumptions:
- 1 FT per enemy FT/BO/RC/SS
- 2 FT per enemy CV/HB
- 4 FTs per enemy DE
- 6 FTs per enemy FR
Remember that the presence of other ships will destroy some of your Fighters. So, provide a few extra Fighters to absorb the extra damage. What we need here is a percentage to figure the FTs that will bleed off.
Heavy Bombers Use the 3.5/8.5 Rule
The 3.5/8.5 rule provides estimates for using Heavy Bombers against Cruisers and Heavy Cruisers. The numbers represent the following assumptions:
- 3.5 per enemy CR/CA
- 8.5 per ememy HC
Destroyers Use the 3/7 Rule
If you’d rather use Destroyers against Cruisers and Heavy Cruisers, use the 3/7 rule. Notice how close this rule is the the Heavy Bomber? This ratio should work for Frigates as well, but you have to push your Missile tech. Destroyers use Plasma, which we tend to push anyway because of Cruisers.
- 3 Destroyers per enemy CR/CA
- 7 Destroyers per enemy HC/FC
Cruisers and Heavy Cruisers
Cruisers yield about a 10:6 ratio against Dreadnaughts.  Twenty HCs will take out a Dreadnought, but with a 9:8 ratio. This is less efficient. So, bring the extra Cruisers.
Heavy Cruisers yield a 2:1 kill ratio against Titans. However, you need 60 HCs per Titan. Bring your HCs after the Fighter and Heavy Bomber waves. You will need about 200 HCs to kill a Leviathan, for a 2:1 ratio.
The ratios mentioned here derive from my unit comparison chart, which tries to show unit ratios needed at “optimal” technology levels. The actual ratios are highly dependent upon the technology of both the attacker and defender.
Attacking Massive Units===
Say you want to target a “naked” Dread—a Dreadnought that has no escort. This is more likely to occur when there’s a gullible character or some other defense (e.g. prings) in play.  But, you don’t know what to bring. All you have at your disposal are Fighters or some other small unit (e.g. Frigates). The problem is the Power of the Fighter is maybe 4, and the Dread has a Shield of 30. So, it sounds impossible.
The math is simpler, actually. We know that at least one percent of these smaller units pass. So, we know that 0.04 of the Fighter passes through. If you’ve followed my advice, you know what the Dread’s Armour is (say 512). Divide that Armour value by one percent of the attacking units Power. In this case 12800. That’s how many Fighters in this scenario one-shot-kill the Dread.
That sounds like a lot to some, perhaps. The question is: how many Fighters are killed. This is simple math as well. Just divide the Power of the Dread by the Armour of your Fighters. Assuming the Dread Power is 982, then 256 Fighters will perish in the ordeal—two percent of the 12800 Fighters.
This means you could go in with fewer fighters and repeat the attack. If you went in with 4200 Fighters (¼), you’d need more than four waves. But, in the end the Dread would be dead.
Of course, if the naked Dread has any other protection (prings), then you have to take that into account.
Look at my Whither Thou Death Star article for more useful information on attacking massive units.


Beers
- Rating
- Description
- Famous Quote
- Beer Advocate
-
Anderson Valley | Blood Orange Gose
- 2/10
- Very thin, citrus lemon, very effervescent
- "Like that girl who went for 3 years to get her masters for something stupid and still doesn't know anything about it."
- 88
-
Sumsung Series 6 J6300
- $600
- 5/5
- 1080p
- LED
- 47.6 inches
- 800Hz
- 2015
- mpeg4
- 1 Side
- 3 Port
- 1 Rear
-
Sumsung Series 6 J6300
- $600
- 5/5
- 1080p
- LED
- 47.6 inches
- 800Hz
- 2015
- mpeg4
- 1 Side
- 3 Port
- 1 Rear
-
Sumsung Series 6 J6300
- $600
- 5/5
- 1080p
- LED
- 47.6 inches
- 800Hz
- 2015
- mpeg4
- 1 Side
- 3 Port
- 1 Rear
-
Sumsung Series 6 J6300
- $600
- 5/5
- 1080p
- LED
- 47.6 inches
- 800Hz
- 2015
- mpeg4
- 1 Side
- 3 Port
- 1 Rear
-
Sumsung Series 6 J6300
- $600
- 5/5
- 1080p
- LED
- 47.6 inches
- 800Hz
- 2015
- mpeg4
- 1 Side
- 3 Port
- 1 Rear
-
Sumsung Series 6 J6300
- $600
- 5/5
- 1080p
- LED
- 47.6 inches
- 800Hz
- 2015
- mpeg4
- 1 Side
- 3 Port
- 1 Rear
-
Sumsung Series 6 J6300
- $600
- 5/5
- 1080p
- LED
- 47.6 inches
- 800Hz
- 2015
- mpeg4
- 1 Side
- 3 Port
- 1 Rear


About Me
Education: I came from Malaysia, graduated from "Foon Yew High School".
Work: I am working as a part time restaurant assistant.
Intrest: I like hands-on activities
Education: I came from Malaysia, graduated from "Foon Yew High School".
Work: I am working as a part time restaurant assistant.
Intrest: I like hands-on activities


You're minutes away from your very own highly configurable Kubernetes cluster. What are you waiting for?
Link an AWS, GCE, Azure, or Digital Ocean account and have a Supergiant cluster up in minutes.


lawstat: Tools for Biostatistics, Public Policy, and Law
Statistical tests widely utilized in biostatistics, public policy, and law. Along with the well-known tests for equality of means and variances, randomness,
measures of relative variability etc, the package contains new robust tests of symmetry,
omnibus and directional tests of normality, and their graphical counterparts such as
Robust QQ plot; a robust trend tests for variances etc. All implemented tests and methods
are illustrated by simulations and real-life examples from legal statistics, economics,
and biostatistics.
| Version: |
3.2 |
| Depends: |
R (≥ 2.6.0), Kendall, mvtnorm, VGAM |
| Suggests: |
fBasics |
| Published: |
2017-11-23 |
| Author: |
Joseph L. Gastwirth [aut],
Yulia R. Gel [aut],
W. L. Wallace Hui [aut],
Vyacheslav Lyubchich [aut, cre],
Weiwen Miao [aut],
Kimihiro Noguchi [aut] |
| Maintainer: |
Vyacheslav Lyubchich <lyubchic at umces.edu> |
| License: |
GPL-2 | GPL-3 [expanded from: GPL (≥ 2)] |
| NeedsCompilation: |
no |
| CRAN checks: |
lawstat results |
Downloads:
Reverse dependencies:
Linking:
Please use the canonical form
https://CRAN.R-project.org/package=lawstat
to link to this page.


This room doesn't use the room's state. It just broadcast messages through "broadcast" method.
User name
Messages


Kardla is the only town on the island. It is small enough to explore on foot and admire its beautiful wooden architecture.
Position 59°00' N, 22°45' 18"E (harbour entrance)
This is a well sheltered, new harbour. There are no berthing fees.
Last updated January 2016.


Preparation time
less than 30 mins
Cooking time
30 mins to 1 hour
Serves
Serves 6
My version of coq au vin, this is just the dish for serving on a cold day.
Put the shallots in a large bowl with the garlic, herbs and wine. Mix, then add the chicken breasts, season with salt and black pepper and marinate for at least 1 hour. When you’re ready to cook, preheat the oven to 160C/140C Fan/Gas 3.
Sit a colander over a large saucepan and strain the marinated chicken, reserving the shallots, bay leaves and thyme. Dab the chicken with kitchen paper to dry it.
Heat the oil and 50g/1¾oz of the butter in a deep ovenproof frying pan or casserole dish. Add the chicken breasts and fry on a medium-high heat, for 5–10 minutes each side, or until browned all over – you may need to do this in batches. Remove with a slotted spoon and set aside.
Meanwhile, set the pan with the wine marinade over a high heat and boil, for 5–10 minutes, until the volume of liquid has reduced by a third. Add the flour to a bowl with 150ml/5fl oz water and whisk until smooth. Stir in a little of the hot wine, and add this mixture to the rest of the wine in the pan. Keep hot.
Add the bacon to the frying pan or casserole dish and fry over a high heat for about 10 minutes, or until browned. Add the reserved shallots and continue to cook for another 10 minutes, or until they start to soften.
Add the hot wine sauce and tomato purée to the frying pan or casserole dish with the sugar, reserved bay leaves, thyme, salt and black pepper and bring to a boil. Stir until thickened and add the browned chicken. Bring back to the boil, cover with a lid and bake for 20–25 minutes, or until cooked through.
Meanwhile, melt the remaining butter in a medium pan and fry the mushrooms over a medium heat for 5–10 minutes, or until just cooked. Add to the chicken casserole just before serving. Remove the bay leaves and thyme from the casserole and serve the casserole hot with mashed potato and shredded cabbage.


About me
Hi, I'm Ellora!
I hail from sunny Nelson and have recently moved to Auckland after spending six years overseas.
Some hobbies of mine include photography, watching cute animal videos on the internet and having a wine or two with some pals, preferably in the sun.
I enrolled in Dev Academy after being introuced to web development a few years ago and playing around with code as a hobby.
I had what I can best describe as a "semi-epiphany" a couple of years ago where I realised that I actually want to work in tech as a career, so here I am!


Home
About Us
Quiz
Feedback
Site Map
This Quiz Contains - 10 - Questions
You Have - 3 Minutes - To Answer Them
Every correct answers carries 2 points
Each Wrong Answers Will Cost You - 1 - Point
Get in touch


class Thread
Threads are the Ruby implementation for a concurrent programming model.
Programs that require multiple threads of execution are a perfect candidate for Ruby's Thread class.
For example, we can create a new thread separate from the main thread's execution using ::new.
thr = Thread.new { puts "Whats the big deal" }
Then we are able to pause the execution of the main thread and allow our new thread to finish, using join:
thr.join #=> "Whats the big deal"
If we don't call thr.join
before the main thread
terminates, then all other threads including thr
will be
killed.
Alternatively, you can use an array for handling multiple threads at once, like in the following example:
threads = [] threads << Thread.new { puts "Whats the big deal" } threads << Thread.new { 3.times { puts "Threads are fun!" } }
After creating a few threads we wait for them all to finish consecutively.
threads.each { |thr| thr.join }
Thread initialization¶ ↑
In order to create new threads, Ruby provides ::new, ::start, and ::fork. A block must be provided with each of these methods, otherwise a ThreadError will be raised.
When subclassing the Thread class, the
initialize
method of your subclass will be ignored by ::start and ::fork. Otherwise, be sure to call
super in your initialize
method.
Thread termination¶ ↑
For terminating threads, Ruby provides a variety of ways to do this.
The class method ::kill, is meant to exit a given thread:
thr = Thread.new { ... } Thread.kill(thr) # sends exit() to thr
Alternatively, you can use the instance method exit, or any of its aliases kill or terminate.
thr.exit
Thread status¶ ↑
Ruby provides a few instance methods for querying the state of a given thread. To get a string with the current thread's state use status
thr = Thread.new { sleep } thr.status # => "sleep" thr.exit thr.status # => false
You can also use alive? to tell if the thread is running or sleeping, and stop? if the thread is dead or sleeping.
Thread variables and scope¶ ↑
Since threads are created with blocks, the same rules apply to other Ruby blocks for variable scope. Any local variables created within this block are accessible to only this thread.
Fiber-local vs. Thread-local¶ ↑
Each fiber has its own bucket for #[] storage. When you set a new fiber-local it is only accessible within this Fiber. To illustrate:
Thread.new { Thread.current[:foo] = "bar" Fiber.new { p Thread.current[:foo] # => nil }.resume }.join
This example uses [] for getting and []= for setting fiber-locals, you can also use keys to list the fiber-locals for a given thread and key? to check if a fiber-local exists.
When it comes to thread-locals, they are accessible within the entire scope of the thread. Given the following example:
Thread.new{ Thread.current.thread_variable_set(:foo, 1) p Thread.current.thread_variable_get(:foo) # => 1 Fiber.new{ Thread.current.thread_variable_set(:foo, 2) p Thread.current.thread_variable_get(:foo) # => 2 }.resume p Thread.current.thread_variable_get(:foo) # => 2 }.join
You can see that the thread-local :foo
carried over into the
fiber and was changed to 2
by the end of the thread.
This example makes use of thread_variable_set to create new thread-locals, and thread_variable_get to reference them.
There is also thread_variables to list all thread-locals, and thread_variable? to check if a given thread-local exists.
Exception handling¶ ↑
Any thread can raise an exception using the raise instance method, which operates similarly to Kernel#raise.
However, it's important to note that an exception that occurs in any
thread except the main thread depends on abort_on_exception. This
option is false
by default, meaning that any unhandled
exception will cause the thread to terminate silently when waited on by
either join or value. You can change this default by
either abort_on_exception=
true
or setting $DEBUG to true
.
With the addition of the class method ::handle_interrupt, you can now handle exceptions asynchronously with threads.
Scheduling¶ ↑
Ruby provides a few ways to support scheduling threads in your program.
The first way is by using the class method ::stop, to put the current running thread to sleep and schedule the execution of another thread.
Once a thread is asleep, you can use the instance method wakeup to mark your thread as eligible for scheduling.
You can also try ::pass, which attempts to pass execution to another thread but is dependent on the OS whether a running thread will switch or not. The same goes for priority, which lets you hint to the thread scheduler which threads you want to take precedence when passing execution. This method is also dependent on the OS and may be ignored on some platforms.
Public Class Methods
Returns the thread debug level. Available only if compiled with THREAD_DEBUG=-1.
static VALUE rb_thread_s_debug(void) { return INT2NUM(rb_thread_debug_enabled); }
Sets the thread debug level. Available only if compiled with THREAD_DEBUG=-1.
static VALUE rb_thread_s_debug_set(VALUE self, VALUE val) { rb_thread_debug_enabled = RTEST(val) ? NUM2INT(val) : 0; return val; }
Returns the status of the global “abort on exception'' condition.
The default is false
.
When set to true
, if any thread is aborted by an exception,
the raised exception will be re-raised in the main thread.
Can also be specified by the global $DEBUG flag or command line option
-d
.
See also ::abort_on_exception=.
There is also an instance level method to set this for a specific thread, see abort_on_exception.
static VALUE rb_thread_s_abort_exc(void) { return GET_THREAD()->vm->thread_abort_on_exception ? Qtrue : Qfalse; }
When set to true
, if any thread is aborted by an exception,
the raised exception will be re-raised in the main thread. Returns the new
state.
Thread.abort_on_exception = true t1 = Thread.new do puts "In new thread" raise "Exception from thread" end sleep(1) puts "not reached"
This will produce:
In new thread prog.rb:4: Exception from thread (RuntimeError) from prog.rb:2:in `initialize' from prog.rb:2:in `new' from prog.rb:2
See also ::abort_on_exception.
There is also an instance level method to set this for a specific thread, see abort_on_exception=.
static VALUE rb_thread_s_abort_exc_set(VALUE self, VALUE val) { GET_THREAD()->vm->thread_abort_on_exception = RTEST(val); return val; }
Returns the currently executing thread.
Thread.current #=> #<Thread:0x401bdf4c run>
static VALUE thread_s_current(VALUE klass) { return rb_thread_current(); }
Wraps the block in a single, VM-global Thread::Mutex#synchronize, returning the value of the block. A thread executing inside the exclusive section will only block other threads which also use the ::exclusive mechanism.
# File prelude.rb, line 11 def self.exclusive warn "Thread.exclusive is deprecated, use Thread::Mutex", caller MUTEX_FOR_THREAD_EXCLUSIVE.synchronize{ yield } end
Terminates the currently running thread and schedules another thread to be run.
If this thread is already marked to be killed, ::exit returns the Thread.
If this is the main thread, or the last thread, exit the process.
static VALUE rb_thread_exit(void) { rb_thread_t *th = GET_THREAD(); return rb_thread_kill(th->self); }
Changes asynchronous interrupt timing.
interrupt means asynchronous event and corresponding procedure by #raise, #kill, signal trap (not supported yet) and main thread termination (if main thread terminates, then all other thread will be killed).
The given hash
has pairs like ExceptionClass =>
:TimingSymbol
. Where the ExceptionClass is the interrupt handled by
the given block. The TimingSymbol can be one of the following symbols:
:immediate
-
Invoke interrupts immediately.
:on_blocking
-
Invoke interrupts while BlockingOperation.
:never
-
Never invoke all interrupts.
BlockingOperation means that the operation will block the calling thread, such as read and write. On CRuby implementation, BlockingOperation is any operation executed without GVL.
Masked asynchronous interrupts are delayed until they are enabled. This method is similar to sigprocmask(3).
NOTE¶ ↑
Asynchronous interrupts are difficult to use.
If you need to communicate between threads, please consider to use another way such as Queue.
Or use them with deep understanding about this method.
Usage¶ ↑
In this example, we can guard from #raise exceptions.
Using the :never
TimingSymbol the RuntimeError exception will always be ignored
in the first block of the main thread. In the second ::handle_interrupt block
we can purposefully handle RuntimeError
exceptions.
th = Thread.new do Thread.handle_interrupt(RuntimeError => :never) { begin # You can write resource allocation code safely. Thread.handle_interrupt(RuntimeError => :immediate) { # ... } ensure # You can write resource deallocation code safely. end } end Thread.pass # ... th.raise "stop"
While we are ignoring the RuntimeError exception, it's safe to write our resource allocation code. Then, the ensure block is where we can safely deallocate your resources.
Guarding from Timeout::Error¶ ↑
In the next example, we will guard from the Timeout::Error exception. This will help prevent from leaking resources when Timeout::Error exceptions occur during normal ensure clause. For this example we use the help of the standard library Timeout, from lib/timeout.rb
require 'timeout' Thread.handle_interrupt(Timeout::Error => :never) { timeout(10){ # Timeout::Error doesn't occur here Thread.handle_interrupt(Timeout::Error => :on_blocking) { # possible to be killed by Timeout::Error # while blocking operation } # Timeout::Error doesn't occur here } }
In the first part of the timeout
block, we can rely on Timeout::Error being ignored. Then in the
Timeout::Error => :on_blocking
block, any operation that
will block the calling thread is susceptible to a Timeout::Error exception being raised.
Stack control settings¶ ↑
It's possible to stack multiple levels of ::handle_interrupt blocks in order to control more than one ExceptionClass and TimingSymbol at a time.
Thread.handle_interrupt(FooError => :never) { Thread.handle_interrupt(BarError => :never) { # FooError and BarError are prohibited. } }
Inheritance with ExceptionClass¶ ↑
All exceptions inherited from the ExceptionClass parameter will be considered.
Thread.handle_interrupt(Exception => :never) { # all exceptions inherited from Exception are prohibited. }
static VALUE rb_thread_s_handle_interrupt(VALUE self, VALUE mask_arg) { VALUE mask; rb_thread_t *th = GET_THREAD(); volatile VALUE r = Qnil; int state; if (!rb_block_given_p()) { rb_raise(rb_eArgError, "block is needed."); } mask = 0; mask_arg = rb_convert_type(mask_arg, T_HASH, "Hash", "to_hash"); rb_hash_foreach(mask_arg, handle_interrupt_arg_check_i, (VALUE)&mask); if (!mask) { return rb_yield(Qnil); } OBJ_FREEZE_RAW(mask); rb_ary_push(th->pending_interrupt_mask_stack, mask); if (!rb_threadptr_pending_interrupt_empty_p(th)) { th->pending_interrupt_queue_checked = 0; RUBY_VM_SET_INTERRUPT(th); } TH_PUSH_TAG(th); if ((state = EXEC_TAG()) == 0) { r = rb_yield(Qnil); } TH_POP_TAG(); rb_ary_pop(th->pending_interrupt_mask_stack); if (!rb_threadptr_pending_interrupt_empty_p(th)) { th->pending_interrupt_queue_checked = 0; RUBY_VM_SET_INTERRUPT(th); } RUBY_VM_CHECK_INTS(th); if (state) { TH_JUMP_TAG(th, state); } return r; }
Causes the given thread
to exit, see also ::exit.
count = 0 a = Thread.new { loop { count += 1 } } sleep(0.1) #=> 0 Thread.kill(a) #=> #<Thread:0x401b3d30 dead> count #=> 93947 a.alive? #=> false
static VALUE rb_thread_s_kill(VALUE obj, VALUE th) { return rb_thread_kill(th); }
Returns an array of Thread objects for all threads that are either runnable or stopped.
Thread.new { sleep(200) } Thread.new { 1000000.times {|i| i*i } } Thread.new { Thread.stop } Thread.list.each {|t| p t}
This will produce:
#<Thread:0x401b3e84 sleep> #<Thread:0x401b3f38 run> #<Thread:0x401b3fb0 sleep> #<Thread:0x401bdf4c run>
VALUE rb_thread_list(void) { VALUE ary = rb_ary_new(); rb_vm_t *vm = GET_THREAD()->vm; rb_thread_t *th = 0; list_for_each(&vm->living_threads, th, vmlt_node) { switch (th->status) { case THREAD_RUNNABLE: case THREAD_STOPPED: case THREAD_STOPPED_FOREVER: rb_ary_push(ary, th->self); default: break; } } return ary; }
Returns the main thread.
static VALUE rb_thread_s_main(VALUE klass) { return rb_thread_main(); }
Creates a new thread executing the given block.
Any args
given to ::new
will be passed to the block:
arr = [] a, b, c = 1, 2, 3 Thread.new(a,b,c) { |d,e,f| arr << d << e << f }.join arr #=> [1, 2, 3]
A ThreadError exception is raised if ::new is called without a block.
If you're going to subclass Thread, be sure
to call super in your initialize
method, otherwise a ThreadError will be raised.
static VALUE thread_s_new(int argc, VALUE *argv, VALUE klass) { rb_thread_t *th; VALUE thread = rb_thread_alloc(klass); if (GET_VM()->main_thread->status == THREAD_KILLED) rb_raise(rb_eThreadError, "can't alloc thread"); rb_obj_call_init(thread, argc, argv); GetThreadPtr(thread, th); if (!threadptr_initialized(th)) { rb_raise(rb_eThreadError, "uninitialized thread - check `%"PRIsVALUE"#initialize'", klass); } return thread; }
Give the thread scheduler a hint to pass execution to another thread. A running thread may or may not switch, it depends on OS and processor.
static VALUE thread_s_pass(VALUE klass) { rb_thread_schedule(); return Qnil; }
Returns whether or not the asynchronous queue is empty.
Since ::handle_interrupt can be used to defer asynchronous events, this method can be used to determine if there are any deferred events.
If you find this method returns true, then you may finish
:never
blocks.
For example, the following method processes deferred asynchronous events immediately.
def Thread.kick_interrupt_immediately Thread.handle_interrupt(Object => :immediate) { Thread.pass } end
If error
is given, then check only for error
type
deferred events.
Usage¶ ↑
th = Thread.new{ Thread.handle_interrupt(RuntimeError => :on_blocking){ while true ... # reach safe point to invoke interrupt if Thread.pending_interrupt? Thread.handle_interrupt(Object => :immediate){} end ... end } } ... th.raise # stop thread
This example can also be written as the following, which you should use to avoid asynchronous interrupts.
flag = true th = Thread.new{ Thread.handle_interrupt(RuntimeError => :on_blocking){ while true ... # reach safe point to invoke interrupt break if flag == false ... end } } ... flag = false # stop thread
static VALUE rb_thread_s_pending_interrupt_p(int argc, VALUE *argv, VALUE self) { return rb_thread_pending_interrupt_p(argc, argv, GET_THREAD()->self); }
Returns the status of the global “report on exception'' condition.
The default is false
.
When set to true
, all threads will report the exception if an
exception is raised in any thread.
See also ::report_on_exception=.
There is also an instance level method to set this for a specific thread, see report_on_exception.
static VALUE rb_thread_s_report_exc(void) { return GET_THREAD()->vm->thread_report_on_exception ? Qtrue : Qfalse; }
When set to true
, all threads will report the exception if an
exception is raised. Returns the new state.
Thread.report_on_exception = true t1 = Thread.new do puts "In new thread" raise "Exception from thread" end sleep(1) puts "In the main thread"
This will produce:
In new thread prog.rb:4: Exception from thread (RuntimeError) from prog.rb:2:in `initialize' from prog.rb:2:in `new' from prog.rb:2 In the main thread
See also ::report_on_exception.
There is also an instance level method to set this for a specific thread, see report_on_exception=.
static VALUE rb_thread_s_report_exc_set(VALUE self, VALUE val) { GET_THREAD()->vm->thread_report_on_exception = RTEST(val); return val; }
Stops execution of the current thread, putting it into a “sleep'' state, and schedules execution of another thread.
a = Thread.new { print "a"; Thread.stop; print "c" } sleep 0.1 while a.status!='sleep' print "b" a.run a.join #=> "abc"
VALUE rb_thread_stop(void) { if (rb_thread_alone()) { rb_raise(rb_eThreadError, "stopping only thread\n\tnote: use sleep to stop forever"); } rb_thread_sleep_deadly(); return Qnil; }
Public Instance Methods
Attribute Reference—Returns the value of a fiber-local variable (current
thread's root fiber if not explicitly inside a Fiber), using either a symbol or a string name. If
the specified variable does not exist, returns nil
.
[ Thread.new { Thread.current["name"] = "A" }, Thread.new { Thread.current[:name] = "B" }, Thread.new { Thread.current["name"] = "C" } ].each do |th| th.join puts "#{th.inspect}: #{th[:name]}" end
This will produce:
#<Thread:0x00000002a54220 dead>: A #<Thread:0x00000002a541a8 dead>: B #<Thread:0x00000002a54130 dead>: C
#[] and #[]= are not thread-local but fiber-local. This confusion did not exist in Ruby 1.8 because fibers are only available since Ruby 1.9. Ruby 1.9 chooses that the methods behaves fiber-local to save following idiom for dynamic scope.
def meth(newvalue) begin oldvalue = Thread.current[:name] Thread.current[:name] = newvalue yield ensure Thread.current[:name] = oldvalue end end
The idiom may not work as dynamic scope if the methods are thread-local and a given block switches fiber.
f = Fiber.new { meth(1) { Fiber.yield } } meth(2) { f.resume } f.resume p Thread.current[:name] #=> nil if fiber-local #=> 2 if thread-local (The value 2 is leaked to outside of meth method.)
For thread-local variables, please see thread_variable_get and thread_variable_set.
static VALUE rb_thread_aref(VALUE thread, VALUE key) { ID id = rb_check_id(&key); if (!id) return Qnil; return rb_thread_local_aref(thread, id); }
Attribute Assignment—Sets or creates the value of a fiber-local variable, using either a symbol or a string.
See also #[].
For thread-local variables, please see thread_variable_set and thread_variable_get.
static VALUE rb_thread_aset(VALUE self, VALUE id, VALUE val) { return rb_thread_local_aset(self, rb_to_id(id), val); }
Returns the status of the thread-local “abort on exception''
condition for this thr
.
The default is false
.
See also abort_on_exception=.
There is also a class level method to set this for all threads, see ::abort_on_exception.
static VALUE rb_thread_abort_exc(VALUE thread) { rb_thread_t *th; GetThreadPtr(thread, th); return th->abort_on_exception ? Qtrue : Qfalse; }
When set to true
, if this thr
is aborted by an
exception, the raised exception will be re-raised in the main thread.
See also abort_on_exception.
There is also a class level method to set this for all threads, see ::abort_on_exception=.
static VALUE rb_thread_abort_exc_set(VALUE thread, VALUE val) { rb_thread_t *th; GetThreadPtr(thread, th); th->abort_on_exception = RTEST(val); return val; }
Adds proc as a handler for tracing.
See #set_trace_func and Kernel#set_trace_func.
static VALUE thread_add_trace_func_m(VALUE obj, VALUE trace) { rb_thread_t *th; GetThreadPtr(obj, th); thread_add_trace_func(th, trace); return trace; }
Returns true
if thr
is running or sleeping.
thr = Thread.new { } thr.join #=> #<Thread:0x401b3fb0 dead> Thread.current.alive? #=> true thr.alive? #=> false
static VALUE rb_thread_alive_p(VALUE thread) { rb_thread_t *th; GetThreadPtr(thread, th); if (rb_threadptr_dead(th)) return Qfalse; return Qtrue; }
Returns the current backtrace of the target thread.
static VALUE rb_thread_backtrace_m(int argc, VALUE *argv, VALUE thval) { return rb_vm_thread_backtrace(argc, argv, thval); }
Returns the execution stack for the target thread—an array containing backtrace location objects.
See Thread::Backtrace::Location for more information.
This method behaves similarly to Kernel#caller_locations except it applies to a specific thread.
static VALUE rb_thread_backtrace_locations_m(int argc, VALUE *argv, VALUE thval) { return rb_vm_thread_backtrace_locations(argc, argv, thval); }
Terminates thr
and schedules another thread to be run.
If this thread is already marked to be killed, exit returns the Thread.
If this is the main thread, or the last thread, exits the process.
VALUE rb_thread_kill(VALUE thread) { rb_thread_t *th; GetThreadPtr(thread, th); if (th->to_kill || th->status == THREAD_KILLED) { return thread; } if (th == th->vm->main_thread) { rb_exit(EXIT_SUCCESS); } thread_debug("rb_thread_kill: %p (%"PRI_THREAD_ID")\n", (void *)th, thread_id_str(th)); if (th == GET_THREAD()) { /* kill myself immediately */ rb_threadptr_to_kill(th); } else { threadptr_check_pending_interrupt_queue(th); rb_threadptr_pending_interrupt_enque(th, eKillSignal); rb_threadptr_interrupt(th); } return thread; }
Returns the ThreadGroup which contains the
given thread, or returns nil
if thr
is not a
member of any group.
Thread.main.group #=> #<ThreadGroup:0x4029d914>
VALUE rb_thread_group(VALUE thread) { rb_thread_t *th; VALUE group; GetThreadPtr(thread, th); group = th->thgroup; if (!group) { group = Qnil; } return group; }
Dump the name, id, and status of thr to a string.
static VALUE rb_thread_inspect(VALUE thread) { VALUE cname = rb_class_path(rb_obj_class(thread)); rb_thread_t *th; const char *status; VALUE str; GetThreadPtr(thread, th); status = thread_status_name(th, TRUE); str = rb_sprintf("#<%"PRIsVALUE":%p", cname, (void *)thread); if (!NIL_P(th->name)) { rb_str_catf(str, "@%"PRIsVALUE, th->name); } if (!th->first_func && th->first_proc) { VALUE loc = rb_proc_location(th->first_proc); if (!NIL_P(loc)) { const VALUE *ptr = RARRAY_CONST_PTR(loc); rb_str_catf(str, "@%"PRIsVALUE":%"PRIsVALUE, ptr[0], ptr[1]); rb_gc_force_recycle(loc); } } rb_str_catf(str, " %s>", status); OBJ_INFECT(str, thread); return str; }
The calling thread will suspend execution and run this thr
.
Does not return until thr
exits or until the given
limit
seconds have passed.
If the time limit expires, nil
will be returned, otherwise
thr
is returned.
Any threads not joined will be killed when the main program exits.
If thr
had previously raised an exception and the ::abort_on_exception or
$DEBUG flags are not set, (so the exception has not yet been processed), it
will be processed at this time.
a = Thread.new { print "a"; sleep(10); print "b"; print "c" } x = Thread.new { print "x"; Thread.pass; print "y"; print "z" } x.join # Let thread x finish, thread a will be killed on exit. #=> "axyz"
The following example illustrates the limit
parameter.
y = Thread.new { 4.times { sleep 0.1; puts 'tick... ' }} puts "Waiting" until y.join(0.15)
This will produce:
tick... Waiting tick... Waiting tick... tick...
static VALUE thread_join_m(int argc, VALUE *argv, VALUE self) { rb_thread_t *target_th; double delay = DELAY_INFTY; VALUE limit; GetThreadPtr(self, target_th); rb_scan_args(argc, argv, "01", &limit); if (!NIL_P(limit)) { delay = rb_num2dbl(limit); } return thread_join(target_th, delay); }
Returns true
if the given string (or symbol) exists as a
fiber-local variable.
me = Thread.current me[:oliver] = "a" me.key?(:oliver) #=> true me.key?(:stanley) #=> false
static VALUE rb_thread_key_p(VALUE self, VALUE key) { rb_thread_t *th; ID id = rb_check_id(&key); GetThreadPtr(self, th); if (!id || !th->local_storage) { return Qfalse; } if (st_lookup(th->local_storage, id, 0)) { return Qtrue; } return Qfalse; }
Returns an array of the names of the fiber-local variables (as Symbols).
thr = Thread.new do Thread.current[:cat] = 'meow' Thread.current["dog"] = 'woof' end thr.join #=> #<Thread:0x401b3f10 dead> thr.keys #=> [:dog, :cat]
static VALUE rb_thread_keys(VALUE self) { rb_thread_t *th; VALUE ary = rb_ary_new(); GetThreadPtr(self, th); if (th->local_storage) { st_foreach(th->local_storage, thread_keys_i, ary); } return ary; }
Terminates thr
and schedules another thread to be run.
If this thread is already marked to be killed, exit returns the Thread.
If this is the main thread, or the last thread, exits the process.
VALUE rb_thread_kill(VALUE thread) { rb_thread_t *th; GetThreadPtr(thread, th); if (th->to_kill || th->status == THREAD_KILLED) { return thread; } if (th == th->vm->main_thread) { rb_exit(EXIT_SUCCESS); } thread_debug("rb_thread_kill: %p (%"PRI_THREAD_ID")\n", (void *)th, thread_id_str(th)); if (th == GET_THREAD()) { /* kill myself immediately */ rb_threadptr_to_kill(th); } else { threadptr_check_pending_interrupt_queue(th); rb_threadptr_pending_interrupt_enque(th, eKillSignal); rb_threadptr_interrupt(th); } return thread; }
show the name of the thread.
static VALUE rb_thread_getname(VALUE thread) { rb_thread_t *th; GetThreadPtr(thread, th); return th->name; }
set given name to the ruby thread. On some platform, it may set the name to pthread and/or kernel.
static VALUE rb_thread_setname(VALUE thread, VALUE name) { #ifdef SET_ANOTHER_THREAD_NAME const char *s = ""; #endif rb_thread_t *th; GetThreadPtr(thread, th); if (!NIL_P(name)) { rb_encoding *enc; StringValueCStr(name); enc = rb_enc_get(name); if (!rb_enc_asciicompat(enc)) { rb_raise(rb_eArgError, "ASCII incompatible encoding (%s)", rb_enc_name(enc)); } name = rb_str_new_frozen(name); #ifdef SET_ANOTHER_THREAD_NAME s = RSTRING_PTR(name); #endif } th->name = name; #if defined(SET_ANOTHER_THREAD_NAME) if (threadptr_initialized(th)) { SET_ANOTHER_THREAD_NAME(th->thread_id, s); } #endif return name; }
Returns whether or not the asynchronous queue is empty for the target thread.
If error
is given, then check only for error
type
deferred events.
See ::pending_interrupt? for more information.
static VALUE rb_thread_pending_interrupt_p(int argc, VALUE *argv, VALUE target_thread) { rb_thread_t *target_th; GetThreadPtr(target_thread, target_th); if (!target_th->pending_interrupt_queue) { return Qfalse; } if (rb_threadptr_pending_interrupt_empty_p(target_th)) { return Qfalse; } else { if (argc == 1) { VALUE err; rb_scan_args(argc, argv, "01", &err); if (!rb_obj_is_kind_of(err, rb_cModule)) { rb_raise(rb_eTypeError, "class or module required for rescue clause"); } if (rb_threadptr_pending_interrupt_include_p(target_th, err)) { return Qtrue; } else { return Qfalse; } } return Qtrue; } }
Returns the priority of thr. Default is inherited from the current thread which creating the new thread, or zero for the initial main thread; higher-priority thread will run more frequently than lower-priority threads (but lower-priority threads can also run).
This is just hint for Ruby thread scheduler. It may be ignored on some platform.
Thread.current.priority #=> 0
static VALUE rb_thread_priority(VALUE thread) { rb_thread_t *th; GetThreadPtr(thread, th); return INT2NUM(th->priority); }
Sets the priority of thr to integer. Higher-priority threads will run more frequently than lower-priority threads (but lower-priority threads can also run).
This is just hint for Ruby thread scheduler. It may be ignored on some platform.
count1 = count2 = 0 a = Thread.new do loop { count1 += 1 } end a.priority = -1 b = Thread.new do loop { count2 += 1 } end b.priority = -2 sleep 1 #=> 1 count1 #=> 622504 count2 #=> 5832
static VALUE rb_thread_priority_set(VALUE thread, VALUE prio) { rb_thread_t *th; int priority; GetThreadPtr(thread, th); #if USE_NATIVE_THREAD_PRIORITY th->priority = NUM2INT(prio); native_thread_apply_priority(th); #else priority = NUM2INT(prio); if (priority > RUBY_THREAD_PRIORITY_MAX) { priority = RUBY_THREAD_PRIORITY_MAX; } else if (priority < RUBY_THREAD_PRIORITY_MIN) { priority = RUBY_THREAD_PRIORITY_MIN; } th->priority = priority; #endif return INT2NUM(th->priority); }
Raises an exception from the given thread. The caller does not have to be
thr
. See Kernel#raise
for more information.
Thread.abort_on_exception = true a = Thread.new { sleep(200) } a.raise("Gotcha")
This will produce:
prog.rb:3: Gotcha (RuntimeError) from prog.rb:2:in `initialize' from prog.rb:2:in `new' from prog.rb:2
static VALUE thread_raise_m(int argc, VALUE *argv, VALUE self) { rb_thread_t *target_th; rb_thread_t *th = GET_THREAD(); GetThreadPtr(self, target_th); threadptr_check_pending_interrupt_queue(target_th); rb_threadptr_raise(target_th, argc, argv); /* To perform Thread.current.raise as Kernel.raise */ if (th == target_th) { RUBY_VM_CHECK_INTS(th); } return Qnil; }
Returns the status of the thread-local “report on exception''
condition for this thr
.
The default is false
.
See also report_on_exception=.
There is also a class level method to set this for all threads, see ::report_on_exception.
static VALUE rb_thread_report_exc(VALUE thread) { rb_thread_t *th; GetThreadPtr(thread, th); return th->report_on_exception ? Qtrue : Qfalse; }
When set to true
, all threads (including the main program)
will report the exception if an exception is raised in this
thr
.
See also report_on_exception.
There is also a class level method to set this for all threads, see ::report_on_exception=.
static VALUE rb_thread_report_exc_set(VALUE thread, VALUE val) { rb_thread_t *th; GetThreadPtr(thread, th); th->report_on_exception = RTEST(val); return val; }
Wakes up thr
, making it eligible for scheduling.
a = Thread.new { puts "a"; Thread.stop; puts "c" } sleep 0.1 while a.status!='sleep' puts "Got here" a.run a.join
This will produce:
a Got here c
See also the instance method wakeup.
VALUE rb_thread_run(VALUE thread) { rb_thread_wakeup(thread); rb_thread_schedule(); return thread; }
Returns the safe level in effect for thr. Setting thread-local safe levels can help when implementing sandboxes which run insecure code.
thr = Thread.new { $SAFE = 1; sleep } Thread.current.safe_level #=> 0 thr.safe_level #=> 1
static VALUE rb_thread_safe_level(VALUE thread) { rb_thread_t *th; GetThreadPtr(thread, th); return INT2NUM(th->safe_level); }
Establishes proc on thr as the handler for tracing, or
disables tracing if the parameter is nil
.
static VALUE thread_set_trace_func_m(VALUE obj, VALUE trace) { rb_thread_t *th; GetThreadPtr(obj, th); rb_threadptr_remove_event_hook(th, call_trace_func, Qundef); if (NIL_P(trace)) { return Qnil; } thread_add_trace_func(th, trace); return trace; }
Returns the status of thr
.
"sleep"
-
Returned if this thread is sleeping or waiting on I/O
"run"
-
When this thread is executing
"aborting"
-
If this thread is aborting
false
-
When this thread is terminated normally
nil
-
If terminated with an exception.
a = Thread.new { raise("die now") } b = Thread.new { Thread.stop } c = Thread.new { Thread.exit } d = Thread.new { sleep } d.kill #=> #<Thread:0x401b3678 aborting> a.status #=> nil b.status #=> "sleep" c.status #=> false d.status #=> "aborting" Thread.current.status #=> "run"
See also the instance methods alive? and stop?
static VALUE rb_thread_status(VALUE thread) { rb_thread_t *th; GetThreadPtr(thread, th); if (rb_threadptr_dead(th)) { if (!NIL_P(th->errinfo) && !FIXNUM_P(th->errinfo) /* TODO */ ) { return Qnil; } return Qfalse; } return rb_str_new2(thread_status_name(th, FALSE)); }
Returns true
if thr
is dead or sleeping.
a = Thread.new { Thread.stop } b = Thread.current a.stop? #=> true b.stop? #=> false
static VALUE rb_thread_stop_p(VALUE thread) { rb_thread_t *th; GetThreadPtr(thread, th); if (rb_threadptr_dead(th)) return Qtrue; if (th->status == THREAD_STOPPED || th->status == THREAD_STOPPED_FOREVER) return Qtrue; return Qfalse; }
Terminates thr
and schedules another thread to be run.
If this thread is already marked to be killed, exit returns the Thread.
If this is the main thread, or the last thread, exits the process.
VALUE rb_thread_kill(VALUE thread) { rb_thread_t *th; GetThreadPtr(thread, th); if (th->to_kill || th->status == THREAD_KILLED) { return thread; } if (th == th->vm->main_thread) { rb_exit(EXIT_SUCCESS); } thread_debug("rb_thread_kill: %p (%"PRI_THREAD_ID")\n", (void *)th, thread_id_str(th)); if (th == GET_THREAD()) { /* kill myself immediately */ rb_threadptr_to_kill(th); } else { threadptr_check_pending_interrupt_queue(th); rb_threadptr_pending_interrupt_enque(th, eKillSignal); rb_threadptr_interrupt(th); } return thread; }
Returns true
if the given string (or symbol) exists as a
thread-local variable.
me = Thread.current me.thread_variable_set(:oliver, "a") me.thread_variable?(:oliver) #=> true me.thread_variable?(:stanley) #=> false
Note that these are not fiber local variables. Please see #[] and #thread_variable_get for more details.
static VALUE rb_thread_variable_p(VALUE thread, VALUE key) { VALUE locals; ID id = rb_check_id(&key); if (!id) return Qfalse; locals = rb_ivar_get(thread, id_locals); if (!RHASH(locals)->ntbl) return Qfalse; if (st_lookup(RHASH(locals)->ntbl, ID2SYM(id), 0)) { return Qtrue; } return Qfalse; }
Returns the value of a thread local variable that has been set. Note that these are different than fiber local values. For fiber local values, please see #[] and #[]=.
Thread local values are carried along with threads, and do not respect fibers. For example:
Thread.new { Thread.current.thread_variable_set("foo", "bar") # set a thread local Thread.current["foo"] = "bar" # set a fiber local Fiber.new { Fiber.yield [ Thread.current.thread_variable_get("foo"), # get the thread local Thread.current["foo"], # get the fiber local ] }.resume }.join.value # => ['bar', nil]
The value “bar” is returned for the thread local, where nil is returned for the fiber local. The fiber is executed in the same thread, so the thread local values are available.
static VALUE rb_thread_variable_get(VALUE thread, VALUE key) { VALUE locals; locals = rb_ivar_get(thread, id_locals); return rb_hash_aref(locals, rb_to_symbol(key)); }
Sets a thread local with key
to value
. Note that
these are local to threads, and not to fibers. Please see #thread_variable_get
and #[] for more information.
static VALUE rb_thread_variable_set(VALUE thread, VALUE id, VALUE val) { VALUE locals; if (OBJ_FROZEN(thread)) { rb_error_frozen("thread locals"); } locals = rb_ivar_get(thread, id_locals); return rb_hash_aset(locals, rb_to_symbol(id), val); }
Returns an array of the names of the thread-local variables (as Symbols).
thr = Thread.new do Thread.current.thread_variable_set(:cat, 'meow') Thread.current.thread_variable_set("dog", 'woof') end thr.join #=> #<Thread:0x401b3f10 dead> thr.thread_variables #=> [:dog, :cat]
Note that these are not fiber local variables. Please see #[] and #thread_variable_get for more details.
static VALUE rb_thread_variables(VALUE thread) { VALUE locals; VALUE ary; locals = rb_ivar_get(thread, id_locals); ary = rb_ary_new(); rb_hash_foreach(locals, keys_i, ary); return ary; }
Waits for thr
to complete, using join, and returns its value or raises
the exception which terminated the thread.
a = Thread.new { 2 + 2 } a.value #=> 4 b = Thread.new { raise 'something went wrong' } b.value #=> RuntimeError: something went wrong
static VALUE thread_value(VALUE self) { rb_thread_t *th; GetThreadPtr(self, th); thread_join(th, DELAY_INFTY); return th->value; }
Marks a given thread as eligible for scheduling, however it may still remain blocked on I/O.
Note: This does not invoke the scheduler, see run for more information.
c = Thread.new { Thread.stop; puts "hey!" } sleep 0.1 while c.status!='sleep' c.wakeup c.join #=> "hey!"
VALUE rb_thread_wakeup(VALUE thread) { if (!RTEST(rb_thread_wakeup_alive(thread))) { rb_raise(rb_eThreadError, "killed thread"); } return thread; }


--- layout: default title: Philosophy permalink: /philosophy/ redirect_from: - /philosophy.html sitemap: priority: 0.4 lastmod: 2014-02-17T00:00:00-00:00 ---
A model of utilizing full stack technologies to develop is being formed, Under this model just only one person or a tiny team has a variety of skills, and be able to use a variety of skills and systematic thinking to complete the product. why is the model in the making? I have summed up the following reasons.
Due to the heritage of human knowledge like as quora and stackoverflow website, couple with the spirit of the open source of the Internet. as a result that a single person have more ability and speed than past to solve the problem.
Due to the prevalence of cloud computing, couple with the rise of micro service, as a result that developers can directly replace the operations person to complete the work about ops.
Due to the accumulate and enhance of abilities of a person or a tiny team, as a result that he is urgent to show his abilities and value of individual.
TDD & BDD Driver
Twelve factors for native Cloud App,http://12factor.net/
Open source principle, open source isn't a commercial business , but a better model to develop
Data Characteristics
Real Time
Quasi Real Time
Non Real Time
Size of business
Language and framework selection
Node.JS
Express
Koa
Easynode
Sails
Java
Spring Boost
JHipster
C/C++
ACE


Gareth Bale: Wales forward risks further rift with Real Madrid over banner
"The first thing he thinks about is Wales, then golf and after that, Real Madrid."
Gareth Bale has been criticised in Spain for prioritising playing for Wales - and finding time for a quick 18 holes - over turning out for his club Real Madrid, and the forward certainly enjoyed himself after helping his country to the finals of Euro 2020.
Bale set up Aaron Ramsey's opener against Hungary and excelled throughout as Wales reached their third major tournament.
The 30-year-old has not played for Real since 5 October and his return to international duty was dubbed by the Spanish media as the 'Miracle in Wales' this week.
Wales fans have turned the mantra 'Wales. Golf. Madrid' into a chant, with Bale himself admitting he found the song amusing.
And after securing qualification Bale was front and central as the squad paraded a banner echoing that sentiment.
And it hasn't gone down so well in Spain...
When asked about the sarcasm aimed at him in Spain as he previewed the game, Bale said: "I've heard some stories but I don't really take notice.
"My friends tend to send me some funny pictures or whatever they write.
"I find it hilarious to be honest, especially some of the pictures and stuff my friends send me. On one, it said 'triple bogey' and I've never had a triple bogey! At least give me an albatross! It's funny.
"Maybe to them [the Spanish media] it doesn't look great but it's just a kind of coincidence that the national team comes around this week and I've returned to full training.
"If I'm fit, no matter where I am, I'm going to try to play, whether it be for Wales or Madrid. For me it was a no-brainer: if I'm fit to play then I'll give it my all."


Contains the common base class for cryptographic hash libraries
The abstract base class for the cryptographic hashes in other libraries, such as SHA1. Contains the common methods for adding data to the hash and generating a digest.
Adds a single byte value to the hash.
| Name | Type | Description |
|---|---|---|
| value | integer | A byte value from 0 to 255 (signed bytes from -128 to -1 are also allowed). |
| Type | Description |
|---|---|
| CryptoCommon.AbstractHash | A reference to itself to allow chaining syntax. |
Adds an integer to the hash. The integer is converted into 32-bit signed Big Endian bytes.
| Name | Type | Description |
|---|---|---|
| value | integer | An integer value |
| Type | Description |
|---|---|
| CryptoCommon.AbstractHash | A reference to itself to allow chaining syntax. |
Adds the string as text to the current hash.
| Name | Type | Optional | Description |
|---|---|---|---|
| value | string | A text value to add to the hash. |
|
| encoding | TextEncoding.TextFormat | Optional | Because cryptographic hashes work with bytes, a string must have an encoding to convert to binary data. If not specified, UTF8 is used. |
| Type | Description |
|---|---|
| CryptoCommon.AbstractHash | A reference to itself to allow chaining syntax. |
Digests the current data into a list of bytes.
| Type | Description |
|---|---|
| int list | A list of bytes from 0 to 255 |
Digests the current data into a (lowercase) hexadecimal string.
| Type | Description |
|---|---|
| string | A hexadecimal hash value |


My name is Edwin Obuya. I am a senior at Point Park University in Pittsburgh, Pennsylvania, pursuing a Bachelors of Science Degree in Information Technology. I have been working in the legal industry for over ten years, and I decided to go back to school to change my career to Software Development. I was born and raised in Mombasa, Kenya.
| Name | Description |
|---|---|
| Advanced Programming | The course focuses on problem solving but with a much higher difficulty level. The students will be required to write programs that involve multiple units of organization, e.g., classes. Several advanced algorithms will be discussed and should be implemented by the students. Prerequisites: CMPS 260. |
| Web Application Development | This course will provide a foundation in several facets of establishing and maintaining a website. This includes the latest advances in client side as well as server side technologies. The goal is to have students design, implement, and run advanced web applications. It will also cover in some detail the protocols required for web development. Prerequisites:CMPS 261, CMPS 262. |
| Accounting I (1st Term) | The basic principles and procedures for gathering, recording, summarizing and interpreting accounting data. |
| Accounting II (2nd Term) | General accounting principles, special procedures for manufacturing operations and analysis of financial and fund statements. Prerequisite: ACCT 101. |
| Corporate Finance | The problems associated with the effective management of capital. Includes the development of corporations, legal aspects, securities market, and financial planning and development. Prerequisites: ACCT 210, MATH 175. |


class: center, middle, inverse, title-slide # Lecture 17 ## Potential Outcomes and Treatment Effects ### Tyler Ransom ### ECON 6343, University of Oklahoma --- # Attribution Today's material is based on lecture notes from Arnaud Maurel (Duke University). I have adjusted his materials to fit the needs and goals of this course --- # Plan for the Day 1. What are potential outcomes? What are treatment effects? 2. Challenges to identifying treatment effects 3. Matching & IV 4. Control functions --- # Potential Outcomes model - Developed by Quandt (1958) and Rubin (1974) - Two potential outcomes, `\((Y_0,Y_1)\)`, associated with each treatment status `\(D\in\{0,1\}\)` - The econometrician only observes: - the treatment dummy `\(D\)` - the realized outcome `\(Y=D Y_1 + (1-D)Y_0\)` - Note: we could have more than two treatments - Note: we also assume .hi[SUTVA]: `\(i\)`'s treatment doesn't affect `\(j\)`'s outcome - SUTVA also known as "no interference" in Judea Pearl's world --- # Objects of interest Individual-level Treatment Effects: - `\(Y_{i1} - Y_{i0},\,\,\,\, i=1,\ldots,N\)` Mean treatment effect parameters: - .hi[Average Treatment Effect (ATE):] `\(\mathbb{E}(Y_1-Y_0)\)` - .hi[Average Treatment on the Treated (ATT):] `\(\mathbb{E}(Y_1-Y_0|D=1)\)` - .hi[Average Treatment on the Untreated (ATU):] `\(\mathbb{E}(Y_1-Y_0|D=0)\)` - No covariates in this simple setting, but we could include them fairly easily --- # Objects of interest (Continued) - Each treatment parameter answers a different question - ATT is most related to the effectiveness of an existing program - ATT does not account for program's cost - We can define many other relevant treatment effect parameters: - Marginal Treatment Effect - Policy Relevant Treatment Effect - These require imposing some structure on the underlying selection model --- # Identification challenges Two main problems arise when identifying the effect of treatment `\(D\)` on outcome `\(Y\)`: 1. .hi[Evaluation problem:] for each `\(i\)` we only observe either `\(Y_0\)` or `\(Y_1\)`, but never both 2. .hi[Selection problem:] selection into treatment is endogenous, i.e. `\((Y_0,Y_1) \not \perp D\)` --- # The evaluation problem - Fundamental observability problem `\(\implies\)` individual TE `\(Y_{i1} - Y_{i0}\)` is not identified - Thus, we often focus on mean treatment effects, such as the ATE, ATT, ATU - Or on other parameters that depend on the marginal distributions only; e.g. QTE - Suppose individuals were randomly assigned across treatment and control groups: `\begin{align*} ATE&=\mathbb{E}(Y_1-Y_0)\\ &=\mathbb{E}(Y_1|D=1) - \mathbb{E}(Y_0|D=0)\\ &=\mathbb{E}(Y|D=1) - \mathbb{E}(Y|D=0) \end{align*}` - Then the ATE would be directly identified from the data (as would be the case for the other average treatment effects; they'd all be equal here) --- # The evaluation problem (Cont'd) - Direct identification of TE from the data is specific to .hi[mean TE's] - Why? They only depend on the marginal distributions of `\(Y_0\)` and `\(Y_1\)` - Other features of the distribution of TE's depend on the joint distribution of `\((Y_0,Y_1)\)` - e.g. variance, median - Additional assumptions would be needed for identification of these --- # The selection problem - .hi[Major difficulty:] Agents often .hi[choose] to be treated based on characteristics which are related to their potential outcomes - Canonical model of self-selection is due to Roy (1951) - Within this framework, selection into treatment is directly based on the TE `\(Y_1-Y_0\)` - Individuals self-select into treatment iff `\(Y_1-Y_0>0\)` - In this case, `\(\mathbb{E}(Y_1|D=1) \neq \mathbb{E}(Y_1)\)` and `\(\mathbb{E}(Y_0|D=0) \neq \mathbb{E}(Y_0)\)` --- # The selection problem (Continued) - The ATE cannot be identified directly from the observed average outcomes - Need to know/assume more about selection rule to identify the TE parameters - Two alternative approaches: point vs. partial identification - Tradeoff strength/identifying power of the invoked assumptions --- # Standard identifying assumptions Three main alternative assumptions to deal with selection. 1. .hi[Unconfoundedness approach (Matching):] `\((Y_0,Y_1) \perp D | X\)`, where `\(X\)` is a set of observed covariates 2. .hi[IV approach:] `\((Y_0,Y_1) \perp Z| X\)`, where `\(X\)` and `\(Z\)` denote two vectors of covariates affecting the potential outcomes and the treatment status, resp. 3. .hi[Control function approach:] `\((Y_0,Y_1) \perp D| X,Z,\nu\)` (where `\(\nu\)` is an unobserved r.v.), plus some structure on the selection equation. (2) and (3) are related in the sense that both hinge on existence of exclusion restrictions --- # Standard identifying assumptions (Cont'd) Panel: most popular method to deal with selection is the difference-in-differences approach, which compares the evolution over time in the outcomes of treated vs. untreated individuals: - `\(\Delta Y_0 \perp D\)` (.hi[parallel trend assumption]), where `\(\Delta Y\)` denotes the variation in the outcome `\(Y\)` between `\(t_0\)` and `\(t_1\)`, with the treatment taking place between `\(t_0\)` and `\(t_1\)` - Accounts for selection on .hi[time-invariant] characteristics - One may combine difference-in-differences with matching, which yields identification under weaker conditions (Heckman, Ichimura, Smith, and Todd, 1998) --- # Matching - Accounts for selection on observables only - Main identifying assumption: `\((Y_0,Y_1) \perp D | X\)` - This is known as the .hi[Conditional Independence Assumption] (CIA), or .hi[Unconfoundedness] - Conditioning on a set of observed covariates `\(X\)` randomizes treatment `\(D\)` - Additional assumption: `\(\mathbb{P}(D=1|X=x) \in (0,1)\)`, for all `\(x\)` in the support of `\(X\)` - Required to be able to compare the outcomes of treated vs. untreated individuals, for any given value of characteristics `\(X=x\)` --- # Matching (Cont'd) - Under these assumptions, the ATE is identified: `\begin{align*} \mathbb{E}(Y_1-Y_0)&=\mathbb{E}(\mathbb{E}(Y_1-Y_0|X))\\ &=\mathbb{E}(\mathbb{E}(Y_1|D=1,X)) - \mathbb{E}(\mathbb{E}(Y_0|D=0,X)) \end{align*}` - Similar for the other average treatment effect parameters - However, distributional TE's are not identified without additional restrictions - Note that the CIA cannot be tested - The second assumption, on the other hand, is directly testable --- # IV The IV approach also deals with selection on unobservables Key identifying assumptions: - Exogeneity: `\((Y_0,Y_1,(D(z))_z)\perp Z | X\)` - Relevance: `\(\mathbb{P}(D=1|X,Z)\)` is a nondegenerate function of `\(Z\)` given `\(X\)` Exogenous variation in the instrument `\(Z\)` (conditional on `\(X\)`) generates variation in `\(D\)` Allows to identify the average treatment effect parameters ... under (strong) restrictions on selection into treatment --- # IV (Cont'd) Regression representation of the treatment effect model: `\begin{align*} Y&=\alpha + \beta D + U \end{align*}` where `\(\alpha=\mathbb{E}(Y_0)\)`, `\(\beta=Y_1-Y_0\)` and `\(U=Y_0-\alpha\)` - It is useful to consider two important cases: - Homogeneous treatment effects ( `\(\beta\)` constant) - Heterogeneous treatment effects, with selection into treatment partly driven by the treatment effects - Sometimes referred to as a model with .hi[essential heterogeneity] (Heckman, Urzua, and Vytlacil, 2006), aka the .hi[correlated random coefficient model] --- # IV: homogeneous treatment effects Unique treatment effect `\((ATE=ATT=ATU=\beta)\)` - We can apply standard IV method to the previous regression, which identifies the treatment effect `\(\beta_{\textrm{IV}} = \frac{Cov(Y,Z)}{Cov(D,Z)}\)` - Special case of a binary instrument `\(Z\)`: Wald estimator - But, assuming homogeneous treatment effects is very restrictive! - In practice, the effectiveness of social programs tends to vary a lot across individuals --- # IV: heterogeneous treatment effects .smaller[ The previous model is a correlated random coefficient model - Key (negative) result: in general, the instrumental approach does not identify the ATE (nor any standard treatment effect parameters) - Consider the previous model, where `\(\overline{\beta}\)` is the ATE and `\(\eta \equiv \beta - \overline{\beta}\)`. We have: `\begin{align*} Y&=\alpha + \overline{\beta} D + (U+\eta D) \end{align*}` - In general, `\(Z\)` is correlated with `\(\eta D\)`, and the IV does not identify the ATE `\(\overline{\beta}\)` - The IV approach still works if selection into treatment is not driven by the idiosyncratic gains `\(\eta\)`, in which case: `\begin{align*} Cov(Z,\eta D)&=\mathbb{E}(Z \eta D)\\ &=\mathbb{E}(ZD \mathbb{E}(\eta|Z,D))=0 \end{align*}` ] --- # IV and Local Average Treatment Effects (LATE) - However, under an additional .hi[monotonicity] assumption, the IV identifies the LATE (Imbens and Angrist, 1994) - Monotonicity assumption ( `\(Z\)` binary): `\(D_{Z=1} \geq D_{Z=0}\)` - All individuals respond to a change in the instrument `\(Z\)` in the same way (Only sufficient, (de Chaisemartin, 2017)) - Under the previous assumptions, we have: `$$\widehat{\beta}_{IV} \overset{p}{\rightarrow} LATE=\mathbb{E}(Y_1 - Y_0|D_{0}=0, D_1=1)$$` - Interpretation: ATE for the subset of individuals who would change their `\(D\)` following a change in `\(Z\)` (.hi[compliers]) --- # IV and Local Average Treatment Effects (Cont'd) - In general, if heterogeneous treatment effects, `\(LATE \neq ATE\)` (or `\(ATT\)`) - Remark: when `\(Z\)` takes more than two values, IV identifies a weighted average of the LATEs - corresponding to a shift in `\(Z\)` from `\(z\)` to `\(z'\)` - for all `\(z\)` and `\(z'\)` in the support of `\(Z\)` such that `\(\mathbb{P}(D=1|Z=z)<\mathbb{P}(D=1|Z=z')\)` - See recent survey by Mogstad and Torgovitsky (2018) - discusses extrapolation of IV/LATE estimates to policy-relevant parameters --- # Control function - Key idea: use an explicit model of the relationship between `\(D\)` and `\((Y_0,Y_1)\)` to correct for selection bias - Main assumption: there exists a variable `\(\nu\)` such that the following conditional independence condition holds: `$$(Y_0,Y_1) \perp D\,\vert\, X,Z,\nu$$` - And some structure is imposed on the selection equation --- # Control function (Cont'd) - This is a fairly general framework - Encompasses many treatment effects models - perfect proxy for `\(\nu\)` available to the econometrician - `\(\nu\)` observed with error as is the case for factor models - ... - Important special case: seminal selection model of Heckman (1979) --- # Control function (Cont'd) - Assume a threshold crossing model for selection into treatment: `\(D=1\left[g(X,Z)-\nu>0\right]\)` - And additively separable potential outcomes: `\(Y_k = \psi_k(X) + \varepsilon_k\)`, with `\((\nu,\varepsilon_0,\varepsilon_1) \perp (X,Z)\)` - `\(\textrm{ATE}(X)=\psi_1(X) - \psi_0(X)\)` - `\(\psi_1(\cdot)\)` is identified from: `\begin{align*} \mathbb{E}(Y_1|X,Z,D=1)&=\psi_1(X) + \mathbb{E}(\varepsilon_1|X,Z,\nu<g(X,Z)) \end{align*}` --- # Control function (Cont'd) - Under regularity conditions (absolute continuity and full support) on the distribution of `\(\nu\)`: `\(g(X,Z)=F^{-1}_{\nu}(\mathbb{P}(D=1|X,Z))\)` - Thus, there exists a function `\(K_1(\cdot)\)` (control function) such that: `\begin{align*} \mathbb{E}(Y_1|X,Z,D=1)&=\psi_1(X) + K_1(\mathbb{P}(D=1|X,Z)) \end{align*}` - This identifies `\(\psi_1(\cdot)\)` .hi[up to location] as long as `\(X\)` and `\(\mathbb{P}(D=1|X,Z)\)` can vary in a sufficiently independent way - measurable separability condition, (Florens, Mouchart, and Rolin, 1990; Florens, Heckman, Meghir, and Vytlacil, 2008) - But, the intercept is crucial to recover the treatment effect parameters! --- # Control function (Cont'd) - Solution: address the selection problem .hi[at the limit], using individuals with treatment probability `\(\mathbb{P}(D=1|X,Z)\)` approaching 1 (0 for `\(\psi_0\)`) to identify the intercept (Heckman, 1990) - For these individuals, `\(K_1(\mathbb{P}(D=1|X,Z))\longrightarrow 0\)`, and therefore: `\(\mathbb{E}(Y_1|X,Z,D=1)=\psi_1(X)\)`, which identifies the intercept. - Key identifying assumption: `\(\textrm{Support}\left(\mathbb{P}(D=1|X,Z)\right) = [0,1]\)` - Note that this is quite restrictive! --- # Control function (Cont'd) Also identifies the treatment effect on the treated and untreated since: `\begin{align*} \mathbb{E}(Y_1-Y_0|X,Z,D=1)&=\mathbb{E}(Y|X,Z,D=1) - \psi_0(X) - \mathbb{E}(\varepsilon_0|X,Z,D=1) \end{align*}` And it follows from the law of iterated expectations that (denoting by `\(p=\mathbb{P}(D=1|X,Z)\)`): `\begin{align*} \mathbb{E}(\varepsilon_0|X,Z,D=1)&=-\frac{1-p}{p}K_{0}(p) \end{align*}` --- # Control function (Cont'd) - Consistent estimators for `\((\psi_0,\psi_1)\)` up to location can be obtained - e.g. semiparametric regression with linear outcomes (Robinson, 1988) - Andrews and Schafgans (1998) provide a consistent estimator for the intercept - smoothed version of Heckman (1990) --- # Further reading - Heckman and Leamer (2007) - Abadie and Cattaneo (2018) - Imbens (2015) - Athey and Imbens (2017) - Deaton (2010) - Heckman (2010) - Imbens and Wooldridge (2009) - Imbens (2004) - Mogstad and Torgovitsky (2018) --- # References .minuscule[ Abadie, A. and M. D. Cattaneo (2018). "Econometric Methods for Program Evaluation". In: _Annual Review of Economics_ 10.1, pp. 465-503. DOI: [10.1146/annurev-economics-080217-053402](https://doi.org/10.1146%2Fannurev-economics-080217-053402). Andrews, D. W. K. and M. M. A. Schafgans (1998). "Semiparametric Estimation of the Intercept of a Sample Selection Model". In: _Review of Economic Studies_ 65.3, pp. 497-517. URL: [http://www.jstor.org/stable/2566936](http://www.jstor.org/stable/2566936). Athey, S. and G. W. Imbens (2017). "The Econometrics of Randomized Experiments". In: _Handbook of Field Experiments_. Ed. by A. V. Banerjee and E. Duflo. Vol. 1. Handbook of Economic Field Experiments. North-Holland. Chap. 3, pp. 73-140. DOI: [10.1016/bs.hefe.2016.10.003](https://doi.org/10.1016%2Fbs.hefe.2016.10.003). Chaisemartin, C. de (2017). "Tolerating Defiance? Local Average Treatment Effects without Monotonicity". In: _Quantitative Economics_ 8.2, pp. 367-396. DOI: [10.3982/QE601](https://doi.org/10.3982%2FQE601). Deaton, A. (2010). "Instruments, Randomization, and Learning about Development". In: _Journal of Economic Literature_ 48.2, pp. 424-455. DOI: [10.1257/jel.48.2.424](https://doi.org/10.1257%2Fjel.48.2.424). Florens, J. P, J. J. Heckman, C. Meghir, et al. (2008). "Identification of Treatment Effects Using Control Functions in Models With Continuous, Endogenous Treatment and Heterogeneous Effects". In: _Econometrica_ 76.5, pp. 1191-1206. DOI: [10.3982/ECTA5317](https://doi.org/10.3982%2FECTA5317). Florens, J. P, M. Mouchart, and J. Rolin (1990). _Elements of Bayesian Statistics_. New York: Dekker. Heckman, J. (1990). "Varieties of Selection Bias". In: _American Economic Review_ 80.2, pp. 313-318. URL: [http://www.jstor.org/stable/2006591](http://www.jstor.org/stable/2006591). Heckman, J. J. (1979). "Sample Selection Bias as a Specification Error". In: _Econometrica_ 47.1, pp. 153-161. DOI: [10.2307/1912352](https://doi.org/10.2307%2F1912352). Heckman, J. J. (2010). "Building Bridges between Structural and Program Evaluation Approaches to Evaluating Policy". In: _Journal of Economic Literature_ 48.2, pp. 356-398. DOI: [10.1257/jel.48.2.356](https://doi.org/10.1257%2Fjel.48.2.356). Heckman, J. J. and E. E. Leamer, ed. (2007). _Handbook of Econometrics, Part 18: Econometric Evaluation of Social Programs_. Vol. 6. Elsevier. DOI: [10.1016/S1573-4412(07)06070-9](https://doi.org/10.1016%2FS1573-4412%2807%2906070-9). Heckman, J. J, S. Urzua, and E. Vytlacil (2006). "Understanding Instrumental Variables in Models with Essential Heterogeneity". In: _Review of Economics and Statistics_ 88.3, pp. 389-432. DOI: [10.1162/rest.88.3.389](https://doi.org/10.1162%2Frest.88.3.389). Heckman, J, H. Ichimura, J. Smith, et al. (1998). "Characterizing Selection Bias Using Experimental Data". In: _Econometrica_ 66.5, pp. 1017-1098. URL: [https://www.jstor.org/stable/2999630](https://www.jstor.org/stable/2999630). Imbens, G. W. (2004). "Nonparametric Estimation of Average Treatment Effects Under Exogeneity: A Review". In: _The Review of Economics and Statistics_ 86.1, pp. 4-29. DOI: [10.1162/003465304323023651](https://doi.org/10.1162%2F003465304323023651). Imbens, G. W. (2015). "Matching Methods in Practice: Three Examples". In: _Journal of Human Resources_ 50.2, pp. 373-419. DOI: [10.3368/jhr.50.2.373](https://doi.org/10.3368%2Fjhr.50.2.373). Imbens, G. W. and J. D. Angrist (1994). "Identification and Estimation of Local Average Treatment Effects". In: _Econometrica_ 62.2, pp. 467-475. DOI: [10.2307/2951620](https://doi.org/10.2307%2F2951620). Imbens, G. W. and J. M. Wooldridge (2009). "Recent Developments in the Econometrics of Program Evaluation". In: _Journal of Economic Literature_ 47.1, pp. 5-86. DOI: [10.1257/jel.47.1.5](https://doi.org/10.1257%2Fjel.47.1.5). Mogstad, M. and A. Torgovitsky (2018). "Identification and Extrapolation of Causal Effects with Instrumental Variables". In: _Annual Review of Economics_ 10.1, pp. 577-613. DOI: [10.1146/annurev-economics-101617-041813](https://doi.org/10.1146%2Fannurev-economics-101617-041813). Quandt, R. E. (1958). "The Estimation of the Parameters of a Linear Regression System Obeying Two Separate Regimes". In: _Journal of the American Statistical Association_ 53.284, pp. 873-880. DOI: [10.1080/01621459.1958.10501484](https://doi.org/10.1080%2F01621459.1958.10501484). Robinson, P. M. (1988). "Root-N-Consistent Semiparametric Regression". In: _Econometrica_ 56.4, pp. 931-954. URL: [http://www.jstor.org/stable/1912705](http://www.jstor.org/stable/1912705). Roy, A. (1951). "Some Thoughts on the Distribution of Earnings". In: _Oxford Economic Papers_ 3.2, pp. 135-146. Rubin, D. B. (1974). "Estimating Causal Effects of Treatments in Randomized and Nonrandomized Studies". In: _Journal of Educational Psychology_ 66.5, pp. 688-701. DOI: [10.1037/h0037350](https://doi.org/10.1037%2Fh0037350). ]