I'm a 5th year PhD Student at the School of Engineering of EPFL and a Research Assistant in the Social Computing Group of Idiap Research Institute advised by Prof. Daniel Gatica-Perez. Previously, I was a Student Researcher at Google Research (Mountain View, CA, USA), Research Intern at the AI Research Lab (Data and Devices Group, Social Dynamics Group) of Nokia Bell Labs (Cambridge, UK), and was also a Visiting Researcher at the Mobile Systems Group of University of Cambridge, hosted by Prof. Cecilia Mascolo.
Currently, I work with multimodal data from smartphones and wearables focusing on aspects such as generalization, personalization, and privacy-preservation of models, with applications towards behavior modeling and healthcare. I also have extensive experience in conducting both in-lab and in-the-wild user studies aiming both quantitative and qualitative analysis.
Before starting my PhD, I worked as a Research Engineer at SMU-CMU Living Analytics Research Centre in Singapore Management University (SMU), Singapore under the supervision of Prof. Archan Misra. I got my BSc in Computer Science and Engineering with a 1st class from University of Moratuwa, Sri Lanka in 2018.
My work has been recognized at prestigious events such as Microsoft Imagine Cup World Finals , Asia Pacific ICT Alliance (APICTA), and National Best Quality ICT Awards (NBQSA, Sri Lanka) and has been covered by local and international press. Further, I was a member of the Sri Lankan International Olympiad team for Astrophysics.
NOTE: If you are a masters/exchange student at EPFL/ETH Zurich interested in a semester project/MS thesis project on using data science and machine learning for research in the intersection of machine/deep learning, multimodal sensing, biomedical AI, and digital health, feel free to drop me an email.
I have studied at:
I have worked at:
I have collaborated with researchers from:
More Information:
| 2023 April | Excited to share that our paper titled "Understanding the Social Context of Eating with Multimodal Smartphone Sensing: The Role of Country Diversity" has been accepted at 25th ACM International Conference on Multimodal Interaction (ICMI) to be held in Paris, France. |
| 2023 July | I've been awarded "Special Recognition for Outstanding Reviews" for my reviews at the 25th ACM International Conference on Multimodal Interaction (ICMI) 2023. |
| 2023 June | Excited to be part of the technical program committees of WellComp and FairComp workshops at ACM Ubicomp 2023, to be held in Cancun, Mexico. Consider submitting your work! |
| 2023 April | Excited to share that our paper titled "Multimodal Earable Sensing for Human Energy Expenditure Estimation" has been accepted at 45th IEEE EMBC 2023 to be held in Sydney, Australia. This is a joint work with Yasith, Darshana, Thilina and Prof. Indika Perera of the Department of Computer Science and Engineering at University of Moratuwa. |
| 2023 April | Excited to be part of the technical program committee of ISWC 2023 (27th International Symposium on Wearable Computers, co-located with Ubicomp). Consider submitting briefs and notes! |
| 2023 April | I've been awarded "Special Recognition for Outstanding Reviews" for my reviews at the ACM IMWUT (Ubicomp) journal, for the review cycle in February 2023. |
| 2023 February | My great pleasure to have given a talk titled "Mobile Sensing and Machine Learning for Health and Well-being: From Personalization to Generalization" at the University of Lausanne. |
| 2023 January | Two first author papers have been accepted at ACM CHI 2023. The first paper, "Quantified Canine 🐕" is from the work I did during my 2022 summer internship at Nokia Bell Labs. With an in-the-wild study, this paper explores the feasibility of using wearables and machine learning to understand dog behavior and personality. The second paper, "Complex Daily Activities, Country-Level Diversity and Smartphone Sensing 🏃" is from the WeNet – The Internet of Us project (w/ Karim Assi co-primary -- an extension of his EPFL semester project). This paper uses smartphone sensor data from over 600 college students in five countries to study activities of daily living. |
| 2022 December | I've been awarded "Special Recognition for Outstanding Reviews" two times at ACM IMWUT (Ubicomp) journal, for review cycles in May and November of 2022. |
| 2022 November | Our paper titled "Your Day in Your Pocket: Complex Activity Recognition from Smartphone Accelerometers" got accepted to the 16th EAI Pervasive Health 2022 conference , to be held in Thessaloniki, Greece in December. This paper is based on Emma Bouton--Bessac's EPFL MS thesis project. |
| 2022 October | Our paper titled "Generalization and Personalization of Mobile Sensing Based Mood Inference Models: An Analysis of Eight Countries" got accepted to the ACM IMWUT (Ubicomp) journal . This is a collaborative work done with partners of the EU Horizon 2020 project WENET. |
| 2023 February | My great pleasure to have given a planery talk titled "Mobile Sensing and Machine Learning for Health and Well-being: From Personalization to Generalization" at ICAPS 2022 Conference at the University of Kelaniya. |
| 2022 September | I joined Google Research (Mountain View, CA, USA) as a Research Intern for the fall of 2022. I am working on an exciting project at the intersection of mobile sensing and machine learning. |
| 2022 June | I will be a member of the technical program committee (TPC) of WellComp 2022 workshop, which will be held at Cambridge, UK (and remote) on the 15th of September 2022, during the ACM UbiComp 2022 conference. Please consider submitting your work! |
| 2022 June | I joined Nokia Bell Labs (Cambridge, UK) as a Research Intern for the summer of 2022. I am working on an exciting project at the intersection of wearable sensing, behavioral and mental health, and machine learning. |
| 2022 May | Super excited to announce that our paper titled "Sensing Eating Events in Context: A Smartphone Only Approach" got accepted to the IEEE Access journal (Impact Factor: 3.75) . This is a collaborative work done with University of Moratuwa, Sri Lanka and IPICYT, Mexico. |
| 2022 March | Excited to share that I have accepted an offer to join Google Research (Mountain View, CA, USA) as a Student Researcher/Research Intern for the fall of 2022. Looking forward to working on an exciting project at the intersection of smartphone sensing and machine learning. |
| 2022 March | Excited to share that I have accepted an offer to join Nokia Bell Labs (Cambridge, UK) as a Research Intern for the summer of 2022. Looking forward to working on an exciting project at the intersection of wearable sensing, signal processing, and machine learning. |
| 2022 February | I gave an invited talk on "Smartphone Sensing for Healthcare" at the Digitalization Week of the University of Lausanne (UNIL), Switzerland. It was an exciting opportunity to talk to people from a range of backgrounds incl. law, social science, and ethics about how AI & sensing impact our lives and privacy. |
| 2021 December | Super excited to share that soon I will be starting as a Visiting Researcher at Mobile Systems Group of the University of Cambridge! I will work with Prof. Cecilia Mascolo at the intersection of smartphone sensing, machine learning, and mental health. |
| 2021 December | I gave a talk on the topic "Smartphone Sensing for the Well-being of Young Adults" at the KnowDive Seminars Series organized by the Knowdive Group of the University of Trento, Italy. Video of the talk can be found here. |
| 2021 October | Excited to share that I've been chosen as a nominee from EPFL for the IBM PhD Fellowship 2022 under the topic "Secure and Trusted AI". |
| 2021 September | I presented two papers (One More Bite , Social Context of Drinking ) at this years ACM Ubicomp 2021 conference. |
| 2021 April | Super excited to announce that our paper titled "Examining the Social Context of Alcohol Drinking in Young Adults with Smartphone Sensing" got accepted to the ACM IMWUT journal. This work will be presented at the ACM UbiComp 2021 conference. |
| 2021 April | Our paper titled "The Theory, Practice, and Ethical Challenges of Designing a Diversity-Aware Platform for Social Relations" has been accepted to the AAAI/ACM Conference on Artificial Intelligence, Ethics, and Society (AIES) 2021. This collaborative work was done as part of the "WeNet – The Internet of Us" project, with wonderful colleagues from the University of Tuebingen, University of Trento, Aalborg University, EPFL (École polytechnique fédérale de Lausanne), Idiap Research Institute, and IPICyT. |
| 2021 April | Our paper titled "Ten Seconds of My Nights: Exploring Different Methods to Measure Brightness, Loudness and Attendance and Their Associations with Alcohol Use using Short Video Clips" got accepted to the PLOS ONE journal. This work was a collaboration between EPFL and Idiap Research Institute (Switzerland), Addiction Switzerland (Switzerland), and La Trobe University (Australia). |
| 2021 January | Our paper titled "One More Bite? Inferring Food Consumption Level of College Students using Smartphone Sensing and Self-Reports" has been accepted for publication at ACM IMWUT journal. The paper will also be presented at UbiComp 2021. This work was a collaboration between EPFL and Idiap Research Institute (Switzerland), IPICYT (Mexico), and University of Trento (Italy). |
| 2020 December | Our paper titled "Smartphone Sensing for the Well-being of Young Adults: A Review" has been accepted for publication at IEEE Access journal (impact factor 3.745 in 2019) |
| 2020 October | Our paper titled "Alone or With Others? Understanding Eating Episodes of College Students with Mobile Sensing" has been accepted to the 19th ACM Conference on Mobile and Ubiquitous Multimedia (MUM) 2020. Acceptance rate is 39%. |
| 2020 October | Our paper titled "Protecting Mobile Food Diaries from Getting to Personal" has been accepted to the 19th ACM Conference on Mobile and Ubiquitous Multimedia (MUM) 2020. Acceptance rate is 39%. |
| 2020 September | Our paper titled "Jointly Optimizing Sensing Pipelines for Multimodal Mixed Reality Interaction" has been accepted to the 17th IEEE Conference on Mobile Ad-Hoc and Smart Systems (MASS) 2020. This work was done in collaboration with Singapore Management University, Singapore and University of Moratuwa, Sri Lanka. Acceptance rate is 30%. |
| 2020 June | Happy to announce that I passed my candidacy exam at School of Engineering, EPFL. Thanks a lot Prof. Daniel and colleagues at EPFL & Idiap for your advice and support. |
| 2020 February | I have been selected as an "Exemplary Reviewer" of IEEE Wireless Communications Letters journal for the year 2019 for the high quality review work. |
| 2020 February | Attended WENET Project meeting at University of Trento, Italy. |
| 2019 November | Paper titled "PokeME: Applying Context-Driven Notifications to Increase Worker Engagement in Mobile Crowd-sourcing" was accepted to ACM SIGIR CHIIR 2020. |
| 2019 November | Paper titled "Change Detection and Notification of Webpages: A Survey" was accepted to ACM Computing Surveys - The ACM Journal with highest impact factor. |
| 2019 October | I attended the WeNet project meeting at Institut d'Investigació en Intel·ligència Artificial (IIIA-CSIC), Barcelona, Spain. |
| 2019 June | Paper titled "Inferring Accurate Bus Trajectories from Noisy Estimated Arrival Time Records" was accepted to IEEE ITSC 2019. |
| 2019 June | Joined EPFL, Switzerland as a Doctoral Student. I will be working with by Prof. Daniel Gatica-Perez. During my PhD, I will work as a Research Assistant in the Social Computing Group of EPFL and Idiap Research Institute. |
| 2019 March | Paper titled "BuSCOPE : Fusing Individual and Aggregated Mobility Behaviorfor "Live" Smart City Services" was accepted to ACM MobiSys 2019. |
| 2019 March | I was offered admission to PhD in Computer Science at University of Cambridge, UK. |
| 2019 February | I was offered admission to PhD in Engineering at Swiss Federal Institute of Technology Lausanne (EPFL). |
| 2018 October | I attended UbiComp 2018 conference held in Singapore. |
| 2018 January | Joined SMU-CMU Living Analytics Research Centre at Singapore Management University (SMU) ,Singapore as a Research Engineer. I will be supervised by Prof. Archan Misra. |
| 2018 January | I graduated from University of Moratuwa, with a 1st class honours degree in Computer Science and Engineering. |
Specialization: Mobile Health Sensing
Thesis: Generalization and Personalization of Machine Learning for Multimodal Mobile Sensing in Everyday Life
Advised by: Prof. Daniel Gatica-Perez
Major: Computer Science and Engineering
Thesis: Change Detection and Notification of Web Pages
Advised by: Prof. Dulani Meedeniya, Prof. Sampath Jayarathna
Major: Management Accounting
Managers: Prof. Daniele Quercia, Dr. Michael Eggleston
Hosted by: Prof. Cecilia Mascolo
Advised by: Prof. Daniel Gatica-Perez
Advised by: Prof. Archan Misra
Collaborations: Prof. Mirco Musolesi
(University College London), Associate Prof. Leman Akoglu (Carnegie Mellon University)
I like to travel and have been to 40 countries around the world so far. One of the things I like to do the most is hiking/trekking. Some milestones I am proud of are Everest Base Camp - Nepal (5364m), Mount Kinabalu - Malaysia (4095m), Volcano Semeru - Indonesia (3676m), Kawah Ijen - Indonesia (2799m), Augstenbern - Leichtenstein (2359m). My goal is to travel to 100 countries and to climb atleast a few 6000m+ peaks. Here are some highlights from my adventures.
I have a youtube channel where I post my travel videos. The equipment I use are Sony A7III mirrorless camera, GoPro Hero 6, and last but no least, the DJI Mavic Air drone. Check out my videos below.
Last Updated: 23 September 2022


Before Change
self.SetIcon(get_icon())
def load_measurements(self, measurements_file_name):
handles = loadmat(measurements_file_name, struct_as_record=True)
m = handles["handles"][0,0][cpp.MEASUREMENTS][0,0]
self.measurements = cpmeas.Measurements()
for object_name in m.dtype.fields.keys():
omeas = m[object_name][0,0]
for feature_name in omeas.dtype.fields.keys():
if object_name == cpmeas.IMAGE:
After Change
def load_measurements(self, measurements_file_name):
self.measurements = cpmeas.Measurements()
self.measurements.load(measurements_file_name)
def on_run(self, event):
image_set_list = cpi.ImageSetList()
image_set = image_set_list.get_image_set(0)


nfsd_selinux
Section: nfsd SELinux Policy documentation (8)Updated: nfsd
Index Return to Main Contents
NAME
nfsd_selinux - Security Enhanced Linux Policy for the nfsd processesDESCRIPTION
BOOLEANS
SELinux policy is customizable based on least access required. nfsd policy is extremely flexible and has several booleans that allow you to manipulate the policy and run nfsd with the tightest access possible.
If you want to allow virt to manage nfs file, you must turn on the virt_use_nfs boolean.
setsebool -P virt_use_nfs 1
If you want to support NFS home directorie, you must turn on the use_nfs_home_dirs boolean.
setsebool -P use_nfs_home_dirs 1
If you want to allow xen to manage nfs file, you must turn on the xen_use_nfs boolean.
setsebool -P xen_use_nfs 1
If you want to allow ftp servers to use nfs used for public file transfer services, you must turn on the allow_ftpd_use_nfs boolean.
setsebool -P allow_ftpd_use_nfs 1
If you want to allow Git daemon system to access nfs file systems, you must turn on the git_system_use_nfs boolean.
setsebool -P git_system_use_nfs 1
If you want to allow qemu to use nfs file system, you must turn on the qemu_use_nfs boolean.
setsebool -P qemu_use_nfs 1
If you want to allow rsync servers to share nfs files system, you must turn on the rsync_use_nfs boolean.
setsebool -P rsync_use_nfs 1
If you want to allow Cobbler to access nfs file systems, you must turn on the cobbler_use_nfs boolean.
setsebool -P cobbler_use_nfs 1
If you want to allow httpd to access nfs file system, you must turn on the httpd_use_nfs boolean.
setsebool -P httpd_use_nfs 1
If you want to allow sge to access nfs file systems, you must turn on the sge_use_nfs boolean.
setsebool -P sge_use_nfs 1
If you want to allow confined virtual guests to manage nfs file, you must turn on the sanlock_use_nfs boolean.
setsebool -P sanlock_use_nfs 1
If you want to allow samba to export NFS volumes, you must turn on the samba_share_nfs boolean.
setsebool -P samba_share_nfs 1
FILE CONTEXTS
SELinux requires files to have an extended attribute to define the file type.You can see the context of a file using the -Z option to lsP Policy governs the access confined processes have to these files. SELinux nfsd policy is very flexible allowing users to setup their nfsd processes in as secure a method as possible.
The following file types are defined for nfsd:
nfs_t
- Set files with the nfs_t type, if you want to treat the files as nfs data.
nfsd_exec_t
- Set files with the nfsd_exec_t type, if you want to transition an executable to the nfsd_t domain.
- Paths:
-
/usr/sbin/rpc.mountd, /usr/sbin/rpc.nfsd
nfsd_initrc_exec_t
- Set files with the nfsd_initrc_exec_t type, if you want to transition an executable to the nfsd_initrc_t domain.
nfsd_ro_t
- Set files with the nfsd_ro_t type, if you want to treat the files as nfsd read/only content.
nfsd_rw_t
- Set files with the nfsd_rw_t type, if you want to treat the files as nfsd read/write content.
Note: File context can be temporarily modified with the chcon command. If you want to permanently change the file context you need to use the semanage fcontext command. This will modify the SELinux labeling database. You will need to use restorecon to apply the labels.
PROCESS TYPES
SELinux defines process types (domains) for each process running on the systemYou can see the context of a process using the -Z option to psP Policy governs the access confined processes have to files. SELinux nfsd policy is very flexible allowing users to setup their nfsd processes in as secure a method as possible.
The following process types are defined for nfsd:
nfsd_t
Note: semanage permissive -a PROCESS_TYPE can be used to make a process type permissive. Permissive process types are not denied access by SELinux. AVC messages will still be generated.
COMMANDS
semanage fcontext can also be used to manipulate default file context mappings.semanage permissive can also be used to manipulate whether or not a process type is permissive.
semanage module can also be used to enable/disable/install/remove policy modules.
semanage boolean can also be used to manipulate the booleans
system-config-selinux is a GUI tool available to customize SELinux policy settings.
AUTHOR
This manual page was autogenerated by genman.py.SEE ALSO
selinux(8), nfsd(8), semanage(8), restorecon(8), chcon(1) , setsebool(8)Index
This document was created by man2html, using the manual pages.
Time: 05:34:28 GMT, December 24, 2015


29 The colors and crayons library has these blocks: It is intended as a more powerful replacement for the primitive set pen block, including ﬁrst class color support; HSL color speciﬁcation as a better alternative to the HSV that Snap ! inherits from JavaScript; a “fair hue” scale that compensates for the eye’s grouping a wide range of light frequencies as green while labelling mere slivers as orange or yellow; the X11/W3C standard color names; RGB in hexadecimal; a linear color scale (as in the old days, but better) based on fair hues and including shades (darker colors) and grayscale. Another linear scale is a curated set of 100 “crayons,” explained further on the next page. Colors are created by the block (for direct user selection), the color from block to specify a color numerically, or by , which reports the color currently in use by the pen. The from color block reports names or numbers associated with a color: Colors can be created from other colors: The three blocks with pen in their names are improved versions of primitive Pen blocks. In principle set pen, for example, could be implemented using a (hypothetical) set pen to color composed with the color from block, but in fact set pen beneﬁts from knowing how the pen color was set in its previous invocation, so it’s implemented separately from color from. Details in Appendix A. The recommended way to choose a color is from one of two linear scales: the continuous color numbers and the discrete crayons: Color numbers are based on fair hues, a modiﬁcation of the spectrum (rainbow) hue scale that devotes less space to green and more to orange and yellow, as well as promoting brown to a real color. Here is the normal hue scale, for reference: Here is the fair hue scale: Here is the color number scale: (The picture is wider so that pure spectral colors line up with the fair hue scale.) And here are the 100 crayons:


CLI
Installation
Local (in your project’s working directory):
$ npm install tslint typescript --save-dev
Global:
$ npm install tslint typescript -g
Peer dependencies
The typescript
module is a peer dependency of TSLint, which allows you to update the compiler independently from the
linter. This also means that tslint
will have to use the same version of tsc
used to actually compile your sources.
Breaking changes in the latest dev release of typescript@next
might break something in the linter if we haven’t built against that release yet. If this happens to you, you can try:
- picking up
tslint@next
, which may have some bugfixes not released intslint@latest
(see release notes here). - rolling back
typescript
to a known working version.
Usage
Please ensure that the TypeScript source files compile correctly before running the linter.
Usage: tslint [options] [file ...]
Options:
-c, --config configuration file
--force return status code 0 even if there are lint errors
-h, --help display detailed help
-i, --init generate a tslint.json config file in the current working directory
-o, --out output file
-r, --rules-dir rules directory
-s, --formatters-dir formatters directory
-e, --exclude exclude globs from path expansion
-t, --format output format (prose, json, verbose, pmd, msbuild, checkstyle, vso) [default: "prose"]
--test test that tslint produces the correct output for the specified directory
-v, --version current version
By default, TSLint looks for a configuration file named tslint.json
in the directory
of the file being linted and, if not found, searches ancestor directories. Check out the rules section for more details on what rules are available.
tslint accepts the following command-line options:
``` -c, –config: The location of the configuration file that tslint will use to determine which rules are activated and what options to provide to the rules. If no option is specified, the config file named tslint.json is used, so long as it exists in the path. The format of the file is { rules: { /* rules list / } }, where / rules list */ is a key: value comma-seperated list of rulename: rule-options pairs. Rule-options can be either a boolean true/false value denoting whether the rule is used or not, or a list [boolean, …] where the boolean provides the same role as in the non-list case, and the rest of the list are options passed to the rule that will determine what it checks for (such as number of characters for the max-line-length rule, or what functions to ban for the ban rule).
-e, –exclude: A filename or glob which indicates files to exclude from linting. This option can be supplied multiple times if you need multiple globs to indicate which files to exclude.
–force: Return status code 0 even if there are any lint errors. Useful while running as npm script.
-i, –init: Generates a tslint.json config file in the current working directory.
-o, –out: A filename to output the results to. By default, tslint outputs to stdout, which is usually the console where you’re running it from.
-r, –rules-dir: An additional rules directory, for user-created rules. tslint will always check its default rules directory, in node_modules/tslint/lib/rules, before checking the user-provided rules directory, so rules in the user-provided rules directory with the same name as the base rules will not be loaded.
-s, –formatters-dir: An additional formatters directory, for user-created formatters. Formatters are files that will format the tslint output, before writing it to stdout or the file passed in –out. The default directory, node_modules/tslint/build/formatters, will always be checked first, so user-created formatters with the same names as the base formatters will not be loaded.
-t, –format: The formatter to use to format the results of the linter before outputting it to stdout or the file passed in –out. The core formatters are prose (human readable), json (machine readable) and verbose. prose is the default if this option is not used. Other built-in options include pmd, msbuild, checkstyle, and vso. Additonal formatters can be added and used if the –formatters-dir option is set.
–test: Runs tslint on the specified directory and checks if tslint’s output matches the expected output in .lint files. Automatically loads the tslint.json file in the specified directory as the configuration file for the tests. See the full tslint documentation for more details on how this can be used to test custom rules.
-v, –version: The current version of tslint.
-h, –help: Prints this help message. ```


property KernelMode: TKernelMode;
Describes the current kernel mode. See TKernelMode for details.
[See also]:


dfs
dp
topological sort
]
Leetcode 0329. Longest Increasing Path in a Matrix
Problem statement
https://leetcode.com/problems/longest-increasing-path-in-a-matrix/
Solution
This problem is dynamic programming problem, the problem is to understand how to traverse our matrix. Actually we can look at this problem as directed graph, and the goal is to find the longest path. One way to do it is to use bfs, where we start from all nodes with outgoing degree equel to 0
and then traverse all nodes from which we can reach these nodes and so on. Another way is to use dynamic programming (sometimes it is called memoisation here, because it is not the usual way to traverse elements), but in fact it is just usual dynamic programming.
- Let
dfs(x, y)
be an answer for cell with coordinates(x, y)
. In the beginning we define it as1
: there is a path of length1
for sure. - Then we check all neighbours and check answers for them and if we can continue path, we update
ans
. - In the end we check values for all cells and return the maximum one.
Notice, how short and clean you code will be when we use memoisation here, we do not need to bother where to start our traversal, in the end we always reach bottom nodes and they will be traversed first.
Complexity
Time complexity is just O(mn)
, because we have this number of states and for each state we have at most 4
transitions. Space complexity is the same.
Code
class Solution:
def longestIncreasingPath(self, matrix):
m, n = len(matrix), len(matrix[0])
neibs = [(0, -1), (0, 1), (1, 0), (-1, 0)]
@lru_cache(None)
def dfs(x, y):
ans = 1
for dx, dy in neibs:
if 0 <= x+dx < m and 0 <= y+dy <n and matrix[x+dx][y+dy] < matrix[x][y]:
ans = max(ans, dfs(x+dx, y+dy) + 1)
return ans
return max(dfs(i, j) for i, j in product(range(m), range(n)))


We enhance platforms!
- redefine wireless initiatives
- matrix sexy functionalities
- monetize plug-and-play ROI
- syndicate innovative e-services
- monetize mission-critical infomediaries
- expedite 24/7 action-items
- transform visionary ROI
- syndicate sticky users
- whiteboard interactive relationships
- cultivate intuitive metrics
- scale wireless relationships
- maximize cutting-edge deliverables
- deploy collaborative niches


404: Page not found
Oh no! Sorry, we've misplaced that URL or it's pointing to something that doesn't exist. Note that some URLs have changed:
- URLs like http://blog.scottlowe.org/tag/tagname are now located at http://blog.scottlowe.org/tags/#tagname. (Here's the full listing of content tags.)
- URLs like http://blog.scottlowe.org/category/categoryname are now found at http://blog.scottlowe.org/categories/#categoryname. (Here's the page with all the post categories.)
- The site's feed URL has changed from http://blog.scottlowe.org/feed/ to http://blog.scottlowe.org/feed.xml. Please update your feed reader appropriately.
You can also head back home to try finding it again.


Class SmsControllerApi
Represents a collection of functions to interact with the API endpoints
Inherited Members
Namespace: mailslurp.Api
Assembly: mailslurp.dll
Syntax
public class SmsControllerApi : ISmsControllerApi, ISmsControllerApiSync, ISmsControllerApiAsync, IApiAccessor
Constructors
View SourceSmsControllerApi()
Initializes a new instance of the SmsControllerApi class.
Declaration
public SmsControllerApi()
SmsControllerApi(Configuration)
Initializes a new instance of the SmsControllerApi class using Configuration object
Declaration
public SmsControllerApi(Configuration configuration)
Parameters
| Type | Name | Description |
|---|---|---|
| Configuration | configuration | An instance of Configuration |
SmsControllerApi(ISynchronousClient, IAsynchronousClient, IReadableConfiguration)
Initializes a new instance of the SmsControllerApi class using a Configuration object and client instance.
Declaration
public SmsControllerApi(ISynchronousClient client, IAsynchronousClient asyncClient, IReadableConfiguration configuration)
Parameters
| Type | Name | Description |
|---|---|---|
| ISynchronousClient | client | The client interface for synchronous API access. |
| IAsynchronousClient | asyncClient | The client interface for asynchronous API access. |
| IReadableConfiguration | configuration | The configuration object. |
SmsControllerApi(string)
Initializes a new instance of the SmsControllerApi class.
Declaration
public SmsControllerApi(string basePath)
Parameters
| Type | Name | Description |
|---|---|---|
| string | basePath |
Properties
View SourceAsynchronousClient
The client for accessing this underlying API asynchronously.
Declaration
public IAsynchronousClient AsynchronousClient { get; set; }
Property Value
| Type | Description |
|---|---|
| IAsynchronousClient |
Client
The client for accessing this underlying API synchronously.
Declaration
public ISynchronousClient Client { get; set; }
Property Value
| Type | Description |
|---|---|
| ISynchronousClient |
Configuration
Gets or sets the configuration object
Declaration
public IReadableConfiguration Configuration { get; set; }
Property Value
| Type | Description |
|---|---|
| IReadableConfiguration | An instance of the Configuration |
ExceptionFactory
Provides a factory method hook for the creation of exceptions.
Declaration
public ExceptionFactory ExceptionFactory { get; set; }
Property Value
| Type | Description |
|---|---|
| ExceptionFactory |
Methods
View SourceDeleteSmsMessage(Guid, int)
Delete SMS message. Delete an SMS message
Declaration
public void DeleteSmsMessage(Guid smsId, int operationIndex = 0)
Parameters
| Type | Name | Description |
|---|---|---|
| Guid | smsId | |
| int | operationIndex | Index associated with the operation. |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
DeleteSmsMessageAsync(Guid, int, CancellationToken)
Delete SMS message. Delete an SMS message
Declaration
public Task DeleteSmsMessageAsync(Guid smsId, int operationIndex = 0, CancellationToken cancellationToken = default)
Parameters
| Type | Name | Description |
|---|---|---|
| Guid | smsId | |
| int | operationIndex | Index associated with the operation. |
| CancellationToken | cancellationToken | Cancellation Token to cancel the request. |
Returns
| Type | Description |
|---|---|
| Task | Task of void |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
DeleteSmsMessages(Guid?, int)
Delete all SMS messages Delete all SMS messages or all messages for a given phone number
Declaration
public void DeleteSmsMessages(Guid? phoneNumberId = null, int operationIndex = 0)
Parameters
| Type | Name | Description |
|---|---|---|
| Guid? | phoneNumberId | (optional) |
| int | operationIndex | Index associated with the operation. |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
DeleteSmsMessagesAsync(Guid?, int, CancellationToken)
Delete all SMS messages Delete all SMS messages or all messages for a given phone number
Declaration
public Task DeleteSmsMessagesAsync(Guid? phoneNumberId = null, int operationIndex = 0, CancellationToken cancellationToken = default)
Parameters
| Type | Name | Description |
|---|---|---|
| Guid? | phoneNumberId | (optional) |
| int | operationIndex | Index associated with the operation. |
| CancellationToken | cancellationToken | Cancellation Token to cancel the request. |
Returns
| Type | Description |
|---|---|
| Task | Task of void |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
DeleteSmsMessagesWithHttpInfo(Guid?, int)
Delete all SMS messages Delete all SMS messages or all messages for a given phone number
Declaration
public ApiResponse<object> DeleteSmsMessagesWithHttpInfo(Guid? phoneNumberId = null, int operationIndex = 0)
Parameters
| Type | Name | Description |
|---|---|---|
| Guid? | phoneNumberId | (optional) |
| int | operationIndex | Index associated with the operation. |
Returns
| Type | Description |
|---|---|
| ApiResponse<object> | ApiResponse of Object(void) |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
DeleteSmsMessagesWithHttpInfoAsync(Guid?, int, CancellationToken)
Delete all SMS messages Delete all SMS messages or all messages for a given phone number
Declaration
public Task<ApiResponse<object>> DeleteSmsMessagesWithHttpInfoAsync(Guid? phoneNumberId = null, int operationIndex = 0, CancellationToken cancellationToken = default)
Parameters
| Type | Name | Description |
|---|---|---|
| Guid? | phoneNumberId | (optional) |
| int | operationIndex | Index associated with the operation. |
| CancellationToken | cancellationToken | Cancellation Token to cancel the request. |
Returns
| Type | Description |
|---|---|
| Task<ApiResponse<object>> | Task of ApiResponse |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
DeleteSmsMessageWithHttpInfo(Guid, int)
Delete SMS message. Delete an SMS message
Declaration
public ApiResponse<object> DeleteSmsMessageWithHttpInfo(Guid smsId, int operationIndex = 0)
Parameters
| Type | Name | Description |
|---|---|---|
| Guid | smsId | |
| int | operationIndex | Index associated with the operation. |
Returns
| Type | Description |
|---|---|
| ApiResponse<object> | ApiResponse of Object(void) |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
DeleteSmsMessageWithHttpInfoAsync(Guid, int, CancellationToken)
Delete SMS message. Delete an SMS message
Declaration
public Task<ApiResponse<object>> DeleteSmsMessageWithHttpInfoAsync(Guid smsId, int operationIndex = 0, CancellationToken cancellationToken = default)
Parameters
| Type | Name | Description |
|---|---|---|
| Guid | smsId | |
| int | operationIndex | Index associated with the operation. |
| CancellationToken | cancellationToken | Cancellation Token to cancel the request. |
Returns
| Type | Description |
|---|---|
| Task<ApiResponse<object>> | Task of ApiResponse |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
GetBasePath()
Gets the base path of the API client.
Declaration
public string GetBasePath()
Returns
| Type | Description |
|---|---|
| string | The base path |
GetSmsMessage(Guid, int)
Get SMS content including body. Expects SMS to exist by ID. For SMS that may not have arrived yet use the WaitForController. Returns a SMS summary object with content.
Declaration
public SmsDto GetSmsMessage(Guid smsId, int operationIndex = 0)
Parameters
| Type | Name | Description |
|---|---|---|
| Guid | smsId | |
| int | operationIndex | Index associated with the operation. |
Returns
| Type | Description |
|---|---|
| SmsDto | SmsDto |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
GetSmsMessageAsync(Guid, int, CancellationToken)
Get SMS content including body. Expects SMS to exist by ID. For SMS that may not have arrived yet use the WaitForController. Returns a SMS summary object with content.
Declaration
public Task<SmsDto> GetSmsMessageAsync(Guid smsId, int operationIndex = 0, CancellationToken cancellationToken = default)
Parameters
| Type | Name | Description |
|---|---|---|
| Guid | smsId | |
| int | operationIndex | Index associated with the operation. |
| CancellationToken | cancellationToken | Cancellation Token to cancel the request. |
Returns
| Type | Description |
|---|---|
| Task<SmsDto> | Task of SmsDto |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
GetSmsMessagesPaginated(Guid?, int?, int?, string, bool?, DateTime?, DateTime?, int)
Get all SMS messages in all phone numbers in paginated form. . By default returns all SMS messages across all phone numbers sorted by ascending created at date. Responses are paginated. You can restrict results to a list of phone number IDs. You can also filter out read messages
Declaration
public PageSmsProjection GetSmsMessagesPaginated(Guid? phoneNumber = null, int? page = null, int? size = null, string sort = null, bool? unreadOnly = null, DateTime? since = null, DateTime? before = null, int operationIndex = 0)
Parameters
| Type | Name | Description |
|---|---|---|
| Guid? | phoneNumber | Optional receiving phone number to filter SMS messages for (optional) |
| int? | page | Optional page index in SMS list pagination (optional, default to 0) |
| int? | size | Optional page size in SMS list pagination. Maximum size is 100. Use page index and sort to page through larger results (optional, default to 20) |
| string | sort | Optional createdAt sort direction ASC or DESC (optional, default to ASC) |
| bool? | unreadOnly | Optional filter for unread SMS only. All SMS are considered unread until they are viewed in the dashboard or requested directly (optional, default to false) |
| DateTime? | since | Optional filter SMSs received after given date time (optional) |
| DateTime? | before | Optional filter SMSs received before given date time (optional) |
| int | operationIndex | Index associated with the operation. |
Returns
| Type | Description |
|---|---|
| PageSmsProjection | PageSmsProjection |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
GetSmsMessagesPaginatedAsync(Guid?, int?, int?, string, bool?, DateTime?, DateTime?, int, CancellationToken)
Get all SMS messages in all phone numbers in paginated form. . By default returns all SMS messages across all phone numbers sorted by ascending created at date. Responses are paginated. You can restrict results to a list of phone number IDs. You can also filter out read messages
Declaration
public Task<PageSmsProjection> GetSmsMessagesPaginatedAsync(Guid? phoneNumber = null, int? page = null, int? size = null, string sort = null, bool? unreadOnly = null, DateTime? since = null, DateTime? before = null, int operationIndex = 0, CancellationToken cancellationToken = default)
Parameters
| Type | Name | Description |
|---|---|---|
| Guid? | phoneNumber | Optional receiving phone number to filter SMS messages for (optional) |
| int? | page | Optional page index in SMS list pagination (optional, default to 0) |
| int? | size | Optional page size in SMS list pagination. Maximum size is 100. Use page index and sort to page through larger results (optional, default to 20) |
| string | sort | Optional createdAt sort direction ASC or DESC (optional, default to ASC) |
| bool? | unreadOnly | Optional filter for unread SMS only. All SMS are considered unread until they are viewed in the dashboard or requested directly (optional, default to false) |
| DateTime? | since | Optional filter SMSs received after given date time (optional) |
| DateTime? | before | Optional filter SMSs received before given date time (optional) |
| int | operationIndex | Index associated with the operation. |
| CancellationToken | cancellationToken | Cancellation Token to cancel the request. |
Returns
| Type | Description |
|---|---|
| Task<PageSmsProjection> | Task of PageSmsProjection |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
GetSmsMessagesPaginatedWithHttpInfo(Guid?, int?, int?, string, bool?, DateTime?, DateTime?, int)
Get all SMS messages in all phone numbers in paginated form. . By default returns all SMS messages across all phone numbers sorted by ascending created at date. Responses are paginated. You can restrict results to a list of phone number IDs. You can also filter out read messages
Declaration
public ApiResponse<PageSmsProjection> GetSmsMessagesPaginatedWithHttpInfo(Guid? phoneNumber = null, int? page = null, int? size = null, string sort = null, bool? unreadOnly = null, DateTime? since = null, DateTime? before = null, int operationIndex = 0)
Parameters
| Type | Name | Description |
|---|---|---|
| Guid? | phoneNumber | Optional receiving phone number to filter SMS messages for (optional) |
| int? | page | Optional page index in SMS list pagination (optional, default to 0) |
| int? | size | Optional page size in SMS list pagination. Maximum size is 100. Use page index and sort to page through larger results (optional, default to 20) |
| string | sort | Optional createdAt sort direction ASC or DESC (optional, default to ASC) |
| bool? | unreadOnly | Optional filter for unread SMS only. All SMS are considered unread until they are viewed in the dashboard or requested directly (optional, default to false) |
| DateTime? | since | Optional filter SMSs received after given date time (optional) |
| DateTime? | before | Optional filter SMSs received before given date time (optional) |
| int | operationIndex | Index associated with the operation. |
Returns
| Type | Description |
|---|---|
| ApiResponse<PageSmsProjection> | ApiResponse of PageSmsProjection |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
GetSmsMessagesPaginatedWithHttpInfoAsync(Guid?, int?, int?, string, bool?, DateTime?, DateTime?, int, CancellationToken)
Get all SMS messages in all phone numbers in paginated form. . By default returns all SMS messages across all phone numbers sorted by ascending created at date. Responses are paginated. You can restrict results to a list of phone number IDs. You can also filter out read messages
Declaration
public Task<ApiResponse<PageSmsProjection>> GetSmsMessagesPaginatedWithHttpInfoAsync(Guid? phoneNumber = null, int? page = null, int? size = null, string sort = null, bool? unreadOnly = null, DateTime? since = null, DateTime? before = null, int operationIndex = 0, CancellationToken cancellationToken = default)
Parameters
| Type | Name | Description |
|---|---|---|
| Guid? | phoneNumber | Optional receiving phone number to filter SMS messages for (optional) |
| int? | page | Optional page index in SMS list pagination (optional, default to 0) |
| int? | size | Optional page size in SMS list pagination. Maximum size is 100. Use page index and sort to page through larger results (optional, default to 20) |
| string | sort | Optional createdAt sort direction ASC or DESC (optional, default to ASC) |
| bool? | unreadOnly | Optional filter for unread SMS only. All SMS are considered unread until they are viewed in the dashboard or requested directly (optional, default to false) |
| DateTime? | since | Optional filter SMSs received after given date time (optional) |
| DateTime? | before | Optional filter SMSs received before given date time (optional) |
| int | operationIndex | Index associated with the operation. |
| CancellationToken | cancellationToken | Cancellation Token to cancel the request. |
Returns
| Type | Description |
|---|---|
| Task<ApiResponse<PageSmsProjection>> | Task of ApiResponse (PageSmsProjection) |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
GetSmsMessageWithHttpInfo(Guid, int)
Get SMS content including body. Expects SMS to exist by ID. For SMS that may not have arrived yet use the WaitForController. Returns a SMS summary object with content.
Declaration
public ApiResponse<SmsDto> GetSmsMessageWithHttpInfo(Guid smsId, int operationIndex = 0)
Parameters
| Type | Name | Description |
|---|---|---|
| Guid | smsId | |
| int | operationIndex | Index associated with the operation. |
Returns
| Type | Description |
|---|---|
| ApiResponse<SmsDto> | ApiResponse of SmsDto |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
GetSmsMessageWithHttpInfoAsync(Guid, int, CancellationToken)
Get SMS content including body. Expects SMS to exist by ID. For SMS that may not have arrived yet use the WaitForController. Returns a SMS summary object with content.
Declaration
public Task<ApiResponse<SmsDto>> GetSmsMessageWithHttpInfoAsync(Guid smsId, int operationIndex = 0, CancellationToken cancellationToken = default)
Parameters
| Type | Name | Description |
|---|---|---|
| Guid | smsId | |
| int | operationIndex | Index associated with the operation. |
| CancellationToken | cancellationToken | Cancellation Token to cancel the request. |
Returns
| Type | Description |
|---|---|
| Task<ApiResponse<SmsDto>> | Task of ApiResponse (SmsDto) |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
GetUnreadSmsCount(int)
Get unread SMS count Get number of SMS unread. Unread means has not been viewed in dashboard or returned in an email API response
Declaration
public UnreadCount GetUnreadSmsCount(int operationIndex = 0)
Parameters
| Type | Name | Description |
|---|---|---|
| int | operationIndex | Index associated with the operation. |
Returns
| Type | Description |
|---|---|
| UnreadCount | UnreadCount |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
GetUnreadSmsCountAsync(int, CancellationToken)
Get unread SMS count Get number of SMS unread. Unread means has not been viewed in dashboard or returned in an email API response
Declaration
public Task<UnreadCount> GetUnreadSmsCountAsync(int operationIndex = 0, CancellationToken cancellationToken = default)
Parameters
| Type | Name | Description |
|---|---|---|
| int | operationIndex | Index associated with the operation. |
| CancellationToken | cancellationToken | Cancellation Token to cancel the request. |
Returns
| Type | Description |
|---|---|
| Task<UnreadCount> | Task of UnreadCount |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
GetUnreadSmsCountWithHttpInfo(int)
Get unread SMS count Get number of SMS unread. Unread means has not been viewed in dashboard or returned in an email API response
Declaration
public ApiResponse<UnreadCount> GetUnreadSmsCountWithHttpInfo(int operationIndex = 0)
Parameters
| Type | Name | Description |
|---|---|---|
| int | operationIndex | Index associated with the operation. |
Returns
| Type | Description |
|---|---|
| ApiResponse<UnreadCount> | ApiResponse of UnreadCount |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |
GetUnreadSmsCountWithHttpInfoAsync(int, CancellationToken)
Get unread SMS count Get number of SMS unread. Unread means has not been viewed in dashboard or returned in an email API response
Declaration
public Task<ApiResponse<UnreadCount>> GetUnreadSmsCountWithHttpInfoAsync(int operationIndex = 0, CancellationToken cancellationToken = default)
Parameters
| Type | Name | Description |
|---|---|---|
| int | operationIndex | Index associated with the operation. |
| CancellationToken | cancellationToken | Cancellation Token to cancel the request. |
Returns
| Type | Description |
|---|---|
| Task<ApiResponse<UnreadCount>> | Task of ApiResponse (UnreadCount) |
Exceptions
| Type | Condition |
|---|---|
| ApiException | Thrown when fails to make API call |


1 After him reigned a blind man called Anysis, of the town of that name. In his reign Egypt was invaded by Sabacos king of Ethiopia and a great army of Ethiopians.
2 The blind man fled to the marshes, and the Ethiopian ruled Egypt for fifty years, during which he distinguished himself for the following:
3 he would never put to death any Egyptian wrongdoer but sentenced all, according to the severity of their offenses, to raise embankments in their native towns. Thus the towns came to stand yet higher than before;
4 for after first being built on embankments made by the excavators of the canals in the reign of Sesostris, they were yet further raised in the reign of the Ethiopian.
5 Of the towns in Egypt that were raised, in my opinion, Bubastis is especially prominent, where there is also a temple of Bubastis, a building most worthy of note. Other temples are greater and more costly, but none more pleasing to the eye than this. Bubastis is, in the Greek language, Artemis.


Hospitality
Here to serve
All the rules and regulations
sdsk
ndskl
To register for stay, click here
dfdasdasd


The one and only Orientation Committee has strived to bring you, in close association with the always marvelous Parentsday Committee (PC), your first ever working group/tutorial/course/thingy/whatever on university! Since, like, ever! The tutorial will involve you grinding your gears on Deductive Reasoning, Linear Algebra and your first lines of code in Python! Buckle up for your first taste of what we hope will not at all be similar to your first stressfueled and self-hatred induced Functional Programming practical. Enjoy!
The Parents day Committee (PC) organises the annual Parents Day. On this day, the parents of AI students can get to know our study programme, the university, and CognAC. This way they get a peak in the daily lives of their kid(s). Which usually happens somewhere in April, so keep posted!
As stated before, this activity serves to provide you a first peek into working groups, tutorials and the more active part of courses you will encounter during your AI Bachelor. We'll give you the opportunity to try programming and make some Artificial Intelligence related assignments. We hope this will give you a better understanding of what you can expect on a day to day basis and teach you a thing or two. This part of the day will take approximately 1 hour. We advise you to spend around 20 minutes on the Artificial Intelligence related assignments, like logic and math. This way you have plenty of time left to enjoy the fun programming assignment. The assignments can be found below. Good luck!


The UnsavedChangeDetectorBehavior class when added to a form, notifies the user if she or he is about to leave unsaved data in the form.


We need some information from you
Some Details
Your Profile
Before you can use Tournatrack, you must fill in some basic details about yourself.
Complete the form on the left to supply us with those details, then re-visit the page you were trying to access.
Warning
This is the testing version of tournatrack. Unless you are looking to test experimental new features, you should use the stable version: Here


COVID-19 impact on KeyForge
All our lives were impacted by COVID-19, but what was the impact on KeyForge sales? There was a very technical post last month, this one is intended for everyone that cares about KeyForge, but not the details of how to create models.
500 000 fewer decks registered during COVID
This shouldn’t come as a surprise to anyone, during COVID, with the world going in lockdown there were fewer decks registered. With local game stores closed, in person games were hard if not impossible at times and the competitive scene died out entirely. So no decks are being purchased for sealed play and there was no need to buy a bunch of deck to find that one with the combo that could take you to the top of the leaderboards. With people unable to get together and play, they play less and the decks they do purchase will last longer as the novelty doesn’t wear off nearly as fast.
The graph below shows, in blue, how many decks were registered in the master vault since the release up until this article was posted. The gray line indicates how many decks the model predicts would have been registered had COVID-19 never happened. The area between the lowest and highest prediction is shaded in gray and shows the uncertainty of the model.
So the model fits the real data like a glove before COVID-19 measurements got into effect (which is good, it would be a very poor model if it didn’t) and as it projects further into our hypothetical scenario the uncertainty grows (which is expected). It shows that without COVID-19 there would have been around 3.16 million decks registered on August 15th, 2021. With the worst prediction at 2.99 million and the best 3.31 million, which makes the actual number of decks registered at that date, 2.43 million look rather pale in comparison.
So Fantasy Flight Games sold a substantially lower number of KeyForge decks during this period. Obviously this isn’t good for the game, without a global pandemic there would have been at least half a million more decks registered. Note that the number of lost sales is even higher, as not every deck sold is necessarily registered.
The interest in KeyForge didn’t diminish
Do you notice the little nicks in the graph above? Those bumps coincide with new sets being released. With every set being preceded with additional advertisement to create a bit of hype, and simply new cards coming out gets people excited to pick up new decks. The model includes the interest there is to buy new decks upon release, and we can compare this between sets. (Technical details can be found in the previous post, with the latest model available on GitHub )
This graph is a bit harder to grok than the previous one, so let’s pick it apart slowly. Each bell curve represents the interest in the different sets, the more the curve is shifted to the left, the lower the interest was, the more to the right the more decks were sold due to the release of that set. The shape of the curve shows where the model thinks the real value is, so it is more likely to be near the top of the curve than near the bottom. Overlapping curves mean there is a rather large chance there was no real difference between the two sets. The technical term for these curves are probability density functions.
The interest in Call of the Archons, the very first set, is huge compared to the others. Releasing a new game, by Richard Garfield, Ph.D. himself, can have that effect. It being a new game also requires people to pick up a few decks to have a variety of games. So the fact that no-one had a collection yet also made the threshold to buy decks early on lower than right now, where some players have already acquired dozens if not hundreds of decks.
However, we see only minor differences in the interest in other sets released before (Age of Ascension and Worlds Collide) and sets released during the pandemic (Mass Mutation and Dark Tidings). The graphs overlap too much to make a call which ones are worse or better than others with confidence. Which is a good thing here! So, we can conclude that the interest in new KeyForge releases hasn’t faded because of a viral outbreak!
Conclusion
KeyForge is a game intended to be played in person. So it is not surprising that with local game stores and tournaments abruptly becoming unavailable the rate of decks being registered dropped considerably. This must have lead to considerable losses for both game stores and Fantasy Flight Games which produces KeyForge. With 500 000 less decks registered the last year and a half, it also creates the impression that interest in the game died. Though when digging deeper into the data that is clearly shown to be incorrect. People still pony up cash to buy new decks upon the release of a new set as before the pandemic. Which suggests the game is very much alive, but incentives to buy more product between releases (sealed and competitive play or simply the ability to go out, sit in front of someone at the store and play) simply weren’t there. Hopefully that is about to change soon again with life restrictions being lifted and the World Championship coming up in 2022 !
Note that this is all about the number of registered decks, if you are interested in the total number of printed decks, have a look a this post.
Acknowledgements
Archon Arcana has been tracking registered decks from the very beginning and kindly shared the raw data for us to play with (check out their page here).
This post is unofficial Fan Content. The literal and graphical information presented in this project related with KeyForge is copyright of Fantasy Flight Games (FFG). 4DCu.be is not produced by, endorsed by, supported by, or affiliated with FFG.
Liked this post ? You can buy me a coffee


Contact Information:
Bio
Bio
Work
Work
Portfolio
Portfolio
Education
Education
Map
Map
VG Style
VG Style
Buisness
Buisness
Referal
Referal


Summer ends with an explosion of colour in the forests. This is the season known as ‘ruska’, when the autumnal reds, browns and yellows are especially beautiful on the fells of Lapland. September is also a popular time for trekking in northern Finland.
While Finns are going back to work, recalling the summer and planning for the next one, others are still finding their way here. The ground is covered in fallen leaves and the smell of wood smoke fills the air. The woods are dotted with wild edible mushrooms, such as yellow chanterelles and brown porcini.
Finns are taking their boats out of the water, putting their bicycles in the garage, and preparing to get out their skates and skis.
Top 10 Autumn Experiences
- Hiking
- Cycling
- Mushroom picking
- Blueberry picking
- Lingonberry picking
- Walking in nature
- Going to Lapland
- Travelling
- Candle light evenings
- Raking
Autumn Colors
Autumn leaf colour, or ruska to locals, is a spectacular natural phenomenon that paints northern landscapes in deep and soft tones. Covered in forests and wildernesses, Finland is a prime destination for some serious leaf peeping.
The stark contrasts between the four seasons are the main characteristics of the annual natural cycle in Finland. Autumn leaf colour acts as a messenger of sorts; it bids a melancholy farewell to long summer days and serves as a reminder of the dark and cold winter that looms around the corner.
The peak season only lasts for roughly two weeks. The period varies from year to year, but the latter part of September is usually a safe bet when planning a trip.
Visual Harmony
Feeling of harmony and cosiness is often associated with autumn leaf colour. Finding a spot with a good view over the landscape make your everyday worries a distant memory. Add a hot drink with snacks and you’ll catch yourself making excuses for not leaving.
The “ruska” season is popular with photographers, and why wouldn’t it be: the variety of broadleaf trees and conifers as well as berries and moss on the ground provide an array of hues of green, auburn, blue, red and yellow so vivid not capturing them would be a crime.


|
Connected Home over IP
672cf7684
|
Provides a generic implementation of PlatformManager features that works on Zephyr RTOS platforms. More...
#include <include/platform/internal/GenericPlatformManagerImpl_Zephyr.h>
Protected Types | |
| using | ThreadStack = k_thread_stack_t[K_THREAD_STACK_LEN(CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE)] |
Protected Attributes | |
| int | mMaxFd |
| fd_set | mReadSet |
| fd_set | mWriteSet |
| fd_set | mErrorSet |
| timeval | mNextTimeout |
| k_mutex | mChipStackLock |
| ChipDeviceEvent | mChipEventRingBuffer [CHIP_DEVICE_CONFIG_MAX_EVENT_QUEUE_SIZE] |
| k_msgq | mChipEventQueue |
| ThreadStack & | mChipThreadStack |
| k_thread | mChipThread |
| Protected Attributes inherited from chip::DeviceLayer::Internal::GenericPlatformManagerImpl< ImplClass > | |
| AppEventHandler * | mAppEventHandlerList |
Additional Inherited Members | |
| Static Protected Member Functions inherited from chip::DeviceLayer::Internal::GenericPlatformManagerImpl< ImplClass > | |
| static void | HandleMessageLayerActivityChanged (bool messageLayerIsActive) |
Provides a generic implementation of PlatformManager features that works on Zephyr RTOS platforms.
This template contains implementations of selected features from the PlatformManager abstract interface that are suitable for use on Zephyr-based platforms. It is intended to be inherited (directly or indirectly) by the PlatformManagerImpl class, which also appears as the template's ImplClass parameter.
|
protected |
|
inlineexplicitprotected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |


Editing "Testing"
# Testing Utopia websites include a default set of tests, and associated `rake test` tasks. These specs can test against the actual running website. By default, `simplecov` is included for coverage testing. ```bash $ rake coverage test my website should have an accessible front page Finished in 0.44849 seconds (files took 0.15547 seconds to load) 1 example, 0 failures Coverage report generated for RSpec. 5 / 5 LOC (100.0%) covered. ```


The following is a simple example of using the
IndexedDB polyfill
together with the
FileSystem API polyfill
for use in browsers that don't natively implement these APIs, in particular mobile Safari on IOS.
Add photos
Select your photo
Loading...
Current File List


JADE MASK, THE (director: Phil Rosen; screenwriter: George Callahan; cinematographer: Harry Neumann; editor: Richard C. Currier; cast: Sidney Toler (Charlie Chan), Mantan Moreland (Birmingham Brown), Edwin Luke (Edward), Janet Warren (Jean Kent), Edith Evanson (Louise Harper), Al Bridge (Mack, Sheriff), Henry Hall (Inspector Godfrey), Ralph Lewis (Kimball), Frank Reicher (Harper), Hardie Albright (Walter Meeker), Joe Whitehead (Dr. Peabody), Lester Dorr (Michael), Dorothy Granger (Stella Graham), Cyril Delevanti (Roth, the butler), Jack Ingram (Archer), Ralph Lewis (Off. Jim Kimball); Runtime: 66; Monogram; 1945)
Reviewed by Dennis Schwartz
An enjoyable Monogram made Charlie Chan mystery, with much trickery disguising who the real culprit is and a very clever premise but one that is not always well executed. Eccentric, absent-minded inventor Harper (Reicher), is working on a secret war project for the government where he can harden wood into a metal. He built a gas chamber to hide his formula plans, as this acts like a spider's web does where it's easy to get in but not possible to get out. One would get locked in without knowing the voice password which is activated only by Harper's voice and would die from either the gas or if having a gas mask would starve to death from being trapped there. The only two people who know of the chamber and the password, are Harper and his trusted butler for the last 15 years, Roth (Delevanti). His assistant, Walter Meeker (Albright), is known for his honesty, but is still not trusted to know any of the secrets. Meeker, also, expresses an open displeasure for Harper.
On a night that a motorcycle policeman, Jim Kimball, tries to enter the gated house and lab of Harper, Roth also reported to Harper an earlier incident of someone firing a shot on the grounds. Following Harper's request to maintain secrecy, the cop is not allowed in the house but is allowed to search the outside grounds. But unknown to the others, the real officer is killed and the one who kills him puts on his uniform and sneaks into the house.
It's discovered that Harper is missing, and the government considers his work so vital they assign Charlie Chan the case. Sheriff Mack is already here and will assist Chan even though he hasn't a clue of what to do. Only the household guests of Harper are present. It seems that not one of them liked the grouchy Harper, as his sister Louise Harper (Evanson) readily states. She also worked there as a housekeeper, hoping to inherit the house and formula rights some day. His niece is the young and attractive Jean Kent (Warren), who also did housework there. Stella Graham (Granger) was a former strong lady in vaudeville and a master puppeteer, who was employed to build a robotic puppet for Harper. Michael (Dorr), a mute, is employed as a handyman and a chauffeur.
When Harper's body is found on the puppet stage, the autoposy says he died of natural causes but Charlie shows that it was a poison dart inflicted inside his mouth. When Jean is the only one who says she didn't see the cop in the house, Chan becomes suspicious but is satisfied when he learns that she was secretly dating the cop and Harper never allowed anyone in--so she had to sneak him in the house.
A few more bodies show up dead, and Charlie himself is almost killed by a poison dart. Since there is more than one person involved in the murders, they hide the fact that their victims are dead until they've had time to establish an alibi. This is accomplished through working the corpses like a puppeteer does the puppets, therefore it appears as if the dead person is walking.
In the concluding scenes, Lloyd Archer (Ingram) enters the Harper mansion and proclaims he was cheated out of the formula--that his stepfather Harper stole the formula from his real father. Meanwhile Charlie deduces from the clues who the killer and his accomplice are, as all the suspects are gathered in the living room of the mansion for Chan to solve the case and explain how he did it. Charlie has the broken ear of a jaded mask, and whomever it fits is the murderer.
For comedy and for providing more of a hinderance than in helping him solve the case his Number Four Son, Edward (Edwin Luke), and his chauffeur, Birmingham Brown (Moreland), come to stay with him at Harper's place. There was a flurry of one-liners, Confusius-like sayings, and some stereotype racial fright humor by Moreland exhibited. It all made for an entertaining but not totally satisfying film.
REVIEWED ON 9/10/2001 GRADE: B-
Dennis Schwartz: "Ozus' World Movie Reviews"
http://www.sover.net/~ozus
<EMAIL_ADDRESS>© ALL RIGHTS RESERVED DENNIS SCHWARTZ
========== X-RAMR-ID: 29428 X-Language: en X-RT-SourceID: 873 X-RT-AuthorID: 1315 X-RT-RatingText: B-
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


Replace user home in a string with another string. Useful for tildifying a path.
var replaceHomedir = require('replace-homedir');
var shortPath = replaceHomedir('/Users/phated/myProject', '~');
// shortPath === '~/myProject'
replaceHomedir(path, replacement)
Takes a string path
as the first argument and a string or function replacement
as the second argument. If the path
is absolute and begins with the User's homedir, the homedir portion of the path is replaced with replacement
using String#replace.
If path
is not a string, the function will throw.
MIT


This data strategy was evaluated by Gartner against a strategy by PwC, and received Gartner's highest approval. The client moved to implement this within a few months with full stakeholder buy-in across the organization.
This project comprised the conception of a data strategy for a US based hospital chain operating across
3 states. We followed a tailored TOGAF framework for designing the enterprise data strategy. The data
strategy included current state analysis, identification of issues and goals through stakeholder
interviews, proposing a future state, and drawing a transformation road-map, staying mindful of
security, governance, data management, analytics and reporting requirements, as well as other
organizational needs.
My role in this project was quite versatile. I led several phases of the project including the stakeholder
interviews for identifying the current state problems, as well as in drawing up the future state
architecture most suited to eradicate those problems and help achieve the organizational goals. I was also
part of the team which put together a 2 year transformation roadmap to get to the future state.
Technology stack involved overall was Azure Cloud Ecosystem, Epic Health Management System, SAP HANA, Hadoop, Oracle, Informatica as well as Denodo
A large Asian Telco wanted predictive intelligence for ongoing orders to reduce potential delays as the current system only allowed analytics about existing orders after their completion, while the ongoing orders’ analysis and monitoring were rulesbased which required substantial manual effort.
A solution was devised which takes data and inputs from various sources and predicts potential bottlenecks and delays for ongoing orders. The business got intel on delays through:
Python/Django, MySQL, ETLs, Dockers, Jenkins
The client (an electric power company) wanted to reduce the manual effort and cost in their
billing process by taking images of the electric meters, and using them to automatically extract
meter readings and accordingly generate the billing.
Using a dataset of power meter images uploaded by meter-readers across a metropolitan city,
a cloud based solution was developed to extract the billing information from the picture and a
batch service was deployed to the cloud. The project included labeling of the dataset and
training a neural network based segmentation model in conjunction with the AWS ReKognition service
for the text extraction.
AWS, Amazon Rekognition, Amazon Ground Truth, Amazon Sagemaker, Tensorflow
"Pervaaz is the world’s leading solution for learning validation. We work with colleges, universities, employers, and certification providers to create secure, high-quality educational experiences and ensure that learners who play by the rules are honored for their work."
Based on the video and audio stream being captured from candidates taking exams remotely on their laptops, video and audio based anomaly detection solutions were created to help the proctor spot suspicious (possibly unethical) behaviour.
AWS, OpenCV, Tensorflow.JS, Scikit-learn
A large scale retailer with global presence wanted to (on the first transaction) predict the lifetime value of the customer, so that the business can identify and invest in potentially valuable customers early on.
The data available was from the CRM, including data verticals of stores, customer demographics, purchase history, membership, products, as well as product categories and brands. Using a customer base of 5M+, a Machine Learning solution was devised which scored customers on the basis of 3 factors:
AWS, Sagemaker, Alteryx, EMR, Spark, Hive, Tensorflow, Keras
A large scale retailer with global presence wanted to identify professional (surrogate) shoppers who take benefit from subsidised prices and shop in bulk to further sell at premium rates, hurting the company's business.
CRM data was available, and an anomaly detection model was trained to identify shoppers buying products with the goal of profit-making. The problem was challenging because the stores had enforced rule based constraints on some of these products, and there were products whose purchase quantity or price, when compared to other products did not trigger rules. Explainable surrogate models were also trained in order to make the decision-making rationale of the AI quite clear to business.
Within 2 months, 3k+ such shoppers were identified in collaboration with the store management in different regions.
AWS, Sagemaker, EMR, Spark, Tensorflow, Keras, Identification of surrogate shoppers
A large travel retailer wanted to divide their customer base into groups of customers representing a similar behaviour to model their marketing strategies in interest of higher conversion rates and increased ROI.
An AI solution was built using data like user’s profession and employment status, website interaction history, purchase patterns, demographic data and tenure of interaction with the company to divide customer segments into further micro segments in the most similar behaviour. Several tiered customer segments were obtained based on recency, frequency and monetary data plus various other features of the customers.
AWS, Sagemaker, EMR, Spark, Tensorflow, Keras
A global retailer wanted to predict the demand of certain SKUs at regional stores, to aid in logistics decision making as well as in dynamically pricing the SKUs.
Data pipelines were written for the ETL of the data from the Snowflake data warehouse to Amazon S3 storage. LSTMs were used for the time-series prediction modeling. The created model beat the performance of H2o AutoML, and helped the business' decision making on logistics support.
AWS, Sagemaker, EMR, Spark, Tensorflow, Keras, Sales Predictions at user granularity
One of the world's biggest international retail stores (a Louis Vuitton subsidiary) wanted to run campaigns on the behalf of partner brands across their customer base of 5M+ members.
Transactional history of their customers was used to create an AI-powered engine with focus on providing 360 degree view of customers behaviour. As a result, a data driven marketing strategy was designed using the ML model to:
AWS, Sagemaker, EMR, Spark, Tensorflow, Keras, Market Segmentation, Influence Modeling, Propensity Modeling
A top Asian financial services company wanted to automate the process of abnormal activity detection in financial transactions. Their aim was to decrease the frauds happening in their payment methods.
A framework was built for the client to detect outliers based on domain specific rules and various machine learning models. Deep convolutional Auto-encoders were used for abnormal activity risk classification. On the basis of categorical and numerical attributes, transaction profiles were generated and each time an unusual activity was observed a flag was triggered. The solution generated user transaction profiles by obtaining user behaviour according to historic transactions.
Azure, Tensorflow, Keras, Anomaly Detection in Transactional Data
A large telco wanted to increase customer satisfaction level and reduce high attrition rates using a customer 360 report which would allow them to make data-driven decisions for the business executives.
My team helped the client to overcome the challenges with a three-fold approach through:
Google Kubernetes Engine; App Engine; Compute Engine; BigQuery; Data Studio; Google Cloud Storage
The client received approximately 50K customer service emails per month which were filtered down to 20K using Outlook filters. They wanted to find a way to automate classification of emails using artificial intelligence thereby improving both efficiency and customer experience.
A solution was devised with the following approach:
Google Cloud VMs, Google Cloud Storage, Python, Tensorflow
Our client undertook a customer retention initiative and identified re-activation and re-capturing of dormant customers to be an integral part of this.
An AI solution based on customer history, purchase patterns and tenure of interaction with the retailer was developed which predicted the churn probability of a certain customer. The ML model predicted the specific customers whose probability fell below the defined threshold thus allowing for a proactive and targeted reactivation strategy.
AWS, Sagemaker, EMR, Spark, Customer Segmentation
One of our reputed clients wanted to build an intrusion detection system as well as enforce an alerting mechanism in their organisation which could warn them about systems behaving abnormally or performing suspicious activity.
Using the AWS cloud infrastructure, a real-time log ingestion mechanism was enacted to get the data into a data lake. This data was then used for anomaly detection and highlighting the possibly compromised systems. These anomalies would then generate alerts for the management. The AI Engine kept the score of logs from endpoints for anomalies, enabling the alerts based on suspicious behavior indicators.
AWS, Kinesis, Data Stream, Lambda, Elasticsearch, Spark, Flask, ML assisted Cyber-security
A pedestrian detection and tracking solution was devised which was adaptable in diverse settings and applications. The product was tested in-house.
Deep learning, Tracking, Python
OCR, Tesseract, Python
A hyperlocal application which also fetched address records from a number of sources needed an address deduplication mechanism. Addresses were largely duplicated due to subtle differences in records from difference sources. A solution was created for deduplication which used word shingling and token based matching.
Python, NLP, Deduplication
Using camera feeds from installations along public highways, a solution was devised to:
Computer Vision, Visibility, Machine Learning, OpenCV, Scikit Learn, Python
Deep learning, Tracking, Python, Design, Documentation, Biz-dev, ML based Video Surveillance
ELK Stack, Elasticsearch, Logstash, Filebeat, Spark, Anomaly Detection, Unsupervised
3D Design, Fabrication, Brain-Computer-Interface, Machine Learning, Embedded, Beaglebone, Multiclass Classification
Semi-supervised, NLP, Classification, Web-scraping, Python
Image processing, MATLAB
Image Processing, OpenCV, C++


Properties
Properties associate values with a particular class, structure, or enumeration. Stored properties store constant and variable values as part of an instance, whereas computed properties calculate (rather than store) a value. Computed properties are provided by classes, structures, and enumerations. Stored properties are provided only by classes and structures.
Stored and computed properties are usually associated with instances of a particular type. However, properties can also be associated with the type itself. Such properties are known as type properties.
In addition, you can define property observers to monitor changes in a property’s value, which you can respond to with custom actions. Property observers can be added to stored properties you define yourself, and also to properties that a subclass inherits from its superclass.
Stored Properties
In its simplest form, a stored property is a constant or variable that is stored as part of an instance of a particular class or structure. Stored properties can be either variable stored properties (introduced by the var
keyword) or constant stored properties (introduced by the let
keyword).
You can provide a default value for a stored property as part of its definition, as described in Default Property Values. You can also set and modify the initial value for a stored property during initialization. This is true even for constant stored properties, as described in Assigning Constant Properties During Initialization.
The example below defines a structure called FixedLengthRange
, which describes a range of integers whose range length cannot be changed after it is created:
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
// the range represents integer values 0, 1, and 2
rangeOfThreeItems.firstValue = 6
// the range now represents integer values 6, 7, and 8
Instances of FixedLengthRange
have a variable stored property called firstValue
and a constant stored property called length
. In the example above, length
is initialized when the new range is created and cannot be changed thereafter, because it is a constant property.
Stored Properties of Constant Structure Instances
If you create an instance of a structure and assign that instance to a constant, you cannot modify the instance’s properties, even if they were declared as variable properties:
let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
// this range represents integer values 0, 1, 2, and 3
rangeOfFourItems.firstValue = 6
// this will report an error, even though firstValue is a variable property
Because rangeOfFourItems
is declared as a constant (with the let
keyword), it is not possible to change its firstValue
property, even though firstValue
is a variable property.
This behavior is due to structures being value types. When an instance of a value type is marked as a constant, so are all of its properties.
The same is not true for classes, which are reference types. If you assign an instance of a reference type to a constant, you can still change that instance’s variable properties.

Lazy properties are useful when the initial value for a property is dependent on outside factors whose values are not known until after an instance’s initialization is complete. Lazy properties are also useful when the initial value for a property requires complex or computationally expensive setup that should not be performed unless or until it is needed.
The example below uses a lazy stored property to avoid unnecessary initialization of a complex class. This example defines two classes called DataImporter
and DataManager
, neither of which is shown in full:
class DataImporter {
/*
DataImporter is a class to import data from an external file.
The class is assumed to take a nontrivial amount of time to initialize.
*/
var filename = "data.txt"
// the DataImporter class would provide data importing functionality here
}
class DataManager {
lazy var importer = DataImporter()
var data = [String]()
// the DataManager class would provide data management functionality here
}
let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")
// the DataImporter instance for the importer property has not yet been created
The DataManager
class has a stored property called data
, which is initialized with a new, empty array of String
values. Although the rest of its functionality is not shown, the purpose of this DataManager
class is to manage and provide access to this array of String
data.
Part of the functionality of the DataManager
class is the ability to import data from a file. This functionality is provided by the DataImporter
class, which is assumed to take a nontrivial amount of time to initialize. This might be because a DataImporter
instance needs to open a file and read its contents into memory when the DataImporter
instance is initialized.
It is possible for a DataManager
instance to manage its data without ever importing data from a file, so there is no need to create a new DataImporter
instance when the DataManager
itself is created. Instead, it makes more sense to create the DataImporter
instance if and when it is first used.
Because it is marked with the lazy
modifier, the DataImporter
instance for the importer
property is only created when the importer
property is first accessed, such as when its filename
property is queried:
print(manager.importer.filename)
// the DataImporter instance for the importer property has now been created
// Prints "data.txt"
Stored Properties and Instance Variables
If you have experience with Objective-C, you may know that it provides two ways to store values and references as part of a class instance. In addition to properties, you can use instance variables as a backing store for the values stored in a property.
Swift unifies these concepts into a single property declaration. A Swift property does not have a corresponding instance variable, and the backing store for a property is not accessed directly. This approach avoids confusion about how the value is accessed in different contexts and simplifies the property’s declaration into a single, definitive statement. All information about the property—including its name, type, and memory management characteristics—is defined in a single location as part of the type’s definition.
Computed Properties
In addition to stored properties, classes, structures, and enumerations can define computed properties, which do not actually store a value. Instead, they provide a getter and an optional setter to retrieve and set other properties and values indirectly.
struct Point {
var x = 0.0, y = 0.0
}
struct Size {
var width = 0.0, height = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
set(newCenter) {
origin.x = newCenter.x - (size.width / 2)
origin.y = newCenter.y - (size.height / 2)
}
}
}
var square = Rect(origin: Point(x: 0.0, y: 0.0),
size: Size(width: 10.0, height: 10.0))
let initialSquareCenter = square.center
square.center = Point(x: 15.0, y: 15.0)
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
// Prints "square.origin is now at (10.0, 10.0)"
This example defines three structures for working with geometric shapes:
Point
encapsulates the x- and y-coordinate of a point.Size
encapsulates awidth
and aheight
.Rect
defines a rectangle by an origin point and a size.
The Rect
structure also provides a computed property called center
. The current center position of a Rect
can always be determined from its origin
and size
, and so you don’t need to store the center point as an explicit Point
value. Instead, Rect
defines a custom getter and setter for a computed variable called center
, to enable you to work with the rectangle’s center
as if it were a real stored property.
The preceding example creates a new Rect
variable called square
. The square
variable is initialized with an origin point of (0, 0)
, and a width and height of 10
. This square is represented by the blue square in the diagram below.
The square
variable’s center
property is then accessed through dot syntax (square.center
), which causes the getter for center
to be called, to retrieve the current property value. Rather than returning an existing value, the getter actually calculates and returns a new Point
to represent the center of the square. As can be seen above, the getter correctly returns a center point of (5, 5)
.
The center
property is then set to a new value of (15, 15)
, which moves the square up and to the right, to the new position shown by the orange square in the diagram below. Setting the center
property calls the setter for center
, which modifies the x
and y
values of the stored origin
property, and moves the square to its new position.
Shorthand Setter Declaration
If a computed property’s setter does not define a name for the new value to be set, a default name of newValue
is used. Here’s an alternative version of the Rect
structure, which takes advantage of this shorthand notation:
struct AlternativeRect {
var origin = Point()
var size = Size()
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
set {
origin.x = newValue.x - (size.width / 2)
origin.y = newValue.y - (size.height / 2)
}
}
}
Read-Only Computed Properties
A computed property with a getter but no setter is known as a read-only computed property. A read-only computed property always returns a value, and can be accessed through dot syntax, but cannot be set to a different value.
You can simplify the declaration of a read-only computed property by removing the get
keyword and its braces:
struct Cuboid {
var width = 0.0, height = 0.0, depth = 0.0
var volume: Double {
return width * height * depth
}
}
let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
// Prints "the volume of fourByFiveByTwo is 40.0"
This example defines a new structure called Cuboid
, which represents a 3D rectangular box with width
, height
, and depth
properties. This structure also has a read-only computed property called volume
, which calculates and returns the current volume of the cuboid. It doesn’t make sense for volume
to be settable, because it would be ambiguous as to which values of width
, height
, and depth
should be used for a particular volume
value. Nonetheless, it is useful for a Cuboid
to provide a read-only computed property to enable external users to discover its current calculated volume.
Property Observers
Property observers observe and respond to changes in a property’s value. Property observers are called every time a property’s value is set, even if the new value is the same as the property’s current value.
You can add property observers to any stored properties you define, except for lazy stored properties. You can also add property observers to any inherited property (whether stored or computed) by overriding the property within a subclass. You don’t need to define property observers for nonoverridden computed properties, because you can observe and respond to changes to their value in the computed property’s setter. Property overriding is described in Overriding.
You have the option to define either or both of these observers on a property:
willSet
is called just before the value is stored.didSet
is called immediately after the new value is stored.
If you implement a willSet
observer, it’s passed the new property value as a constant parameter. You can specify a name for this parameter as part of your willSet
implementation. If you don’t write the parameter name and parentheses within your implementation, the parameter is made available with a default parameter name of newValue
.
Similarly, if you implement a didSet
observer, it’s passed a constant parameter containing the old property value. You can name the parameter or use the default parameter name of oldValue
. If you assign a value to a property within its own didSet
observer, the new value that you assign replaces the one that was just set.
Here’s an example of willSet
and didSet
in action. The example below defines a new class called StepCounter
, which tracks the total number of steps that a person takes while walking. This class might be used with input data from a pedometer or other step counter to keep track of a person’s exercise during their daily routine.
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
print("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
print("Added \(totalSteps - oldValue) steps")
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// About to set totalSteps to 200
// Added 200 steps
stepCounter.totalSteps = 360
// About to set totalSteps to 360
// Added 160 steps
stepCounter.totalSteps = 896
// About to set totalSteps to 896
// Added 536 steps
The StepCounter
class declares a totalSteps
property of type Int
. This is a stored property with willSet
and didSet
observers.
The willSet
and didSet
observers for totalSteps
are called whenever the property is assigned a new value. This is true even if the new value is the same as the current value.
This example’s willSet
observer uses a custom parameter name of newTotalSteps
for the upcoming new value. In this example, it simply prints out the value that is about to be set.
The didSet
observer is called after the value of totalSteps
is updated. It compares the new value of totalSteps
against the old value. If the total number of steps has increased, a message is printed to indicate how many new steps have been taken. The didSet
observer does not provide a custom parameter name for the old value, and the default name of oldValue
is used instead.
Global and Local Variables
The capabilities described above for computing and observing properties are also available to global variables and local variables. Global variables are variables that are defined outside of any function, method, closure, or type context. Local variables are variables that are defined within a function, method, or closure context.
The global and local variables you have encountered in previous chapters have all been stored variables. Stored variables, like stored properties, provide storage for a value of a certain type and allow that value to be set and retrieved.
However, you can also define computed variables and define observers for stored variables, in either a global or local scope. Computed variables calculate their value, rather than storing it, and they are written in the same way as computed properties.
Type Properties
Instance properties are properties that belong to an instance of a particular type. Every time you create a new instance of that type, it has its own set of property values, separate from any other instance.
You can also define properties that belong to the type itself, not to any one instance of that type. There will only ever be one copy of these properties, no matter how many instances of that type you create. These kinds of properties are called type properties.
Type properties are useful for defining values that are universal to all instances of a particular type, such as a constant property that all instances can use (like a static constant in C), or a variable property that stores a value that is global to all instances of that type (like a static variable in C).
Stored type properties can be variables or constants. Computed type properties are always declared as variable properties, in the same way as computed instance properties.
Type Property Syntax
In C and Objective-C, you define static constants and variables associated with a type as global static variables. In Swift, however, type properties are written as part of the type’s definition, within the type’s outer curly braces, and each type property is explicitly scoped to the type it supports.
You define type properties with the static
keyword. For computed type properties for class types, you can use the class
keyword instead to allow subclasses to override the superclass’s implementation. The example below shows the syntax for stored and computed type properties:
struct SomeStructure {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 1
}
}
enum SomeEnumeration {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 6
}
}
class SomeClass {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 27
}
class var overrideableComputedTypeProperty: Int {
return 107
}
}
Querying and Setting Type Properties
Type properties are queried and set with dot syntax, just like instance properties. However, type properties are queried and set on the type, not on an instance of that type. For example:
print(SomeStructure.storedTypeProperty)
// Prints "Some value."
SomeStructure.storedTypeProperty = "Another value."
print(SomeStructure.storedTypeProperty)
// Prints "Another value."
print(SomeEnumeration.computedTypeProperty)
// Prints "6"
print(SomeClass.computedTypeProperty)
// Prints "27"
The examples that follow use two stored type properties as part of a structure that models an audio level meter for a number of audio channels. Each channel has an integer audio level between 0
and 10
inclusive.
The figure below illustrates how two of these audio channels can be combined to model a stereo audio level meter. When a channel’s audio level is 0
, none of the lights for that channel are lit. When the audio level is 10
, all of the lights for that channel are lit. In this figure, the left channel has a current level of 9
, and the right channel has a current level of 7
:
The audio channels described above are represented by instances of the AudioChannel
structure:
struct AudioChannel {
static let thresholdLevel = 10
static var maxInputLevelForAllChannels = 0
var currentLevel: Int = 0 {
didSet {
if currentLevel > AudioChannel.thresholdLevel {
// cap the new audio level to the threshold level
currentLevel = AudioChannel.thresholdLevel
}
if currentLevel > AudioChannel.maxInputLevelForAllChannels {
// store this as the new overall maximum input level
AudioChannel.maxInputLevelForAllChannels = currentLevel
}
}
}
}
The AudioChannel
structure defines two stored type properties to support its functionality. The first, thresholdLevel
, defines the maximum threshold value an audio level can take. This is a constant value of 10
for all AudioChannel
instances. If an audio signal comes in with a higher value than 10
, it will be capped to this threshold value (as described below).
The second type property is a variable stored property called maxInputLevelForAllChannels
. This keeps track of the maximum input value that has been received by any AudioChannel
instance. It starts with an initial value of 0
.
The AudioChannel
structure also defines a stored instance property called currentLevel
, which represents the channel’s current audio level on a scale of 0
to 10
.
The currentLevel
property has a didSet
property observer to check the value of currentLevel
whenever it is set. This observer performs two checks:
If the new value of
currentLevel
is greater than the allowedthresholdLevel
, the property observer capscurrentLevel
tothresholdLevel
.If the new value of
currentLevel
(after any capping) is higher than any value previously received by anyAudioChannel
instance, the property observer stores the newcurrentLevel
value in themaxInputLevelForAllChannels
type property.
You can use the AudioChannel
structure to create two new audio channels called leftChannel
and rightChannel
, to represent the audio levels of a stereo sound system:
var leftChannel = AudioChannel()
var rightChannel = AudioChannel()
If you set the currentLevel
of the left channel to 7
, you can see that the maxInputLevelForAllChannels
type property is updated to equal 7
:
leftChannel.currentLevel = 7
print(leftChannel.currentLevel)
// Prints "7"
print(AudioChannel.maxInputLevelForAllChannels)
// Prints "7"
If you try to set the currentLevel
of the right channel to 11
, you can see that the right channel’s currentLevel
property is capped to the maximum value of 10
, and the maxInputLevelForAllChannels
type property is updated to equal 10
:
rightChannel.currentLevel = 11
print(rightChannel.currentLevel)
// Prints "10"
print(AudioChannel.maxInputLevelForAllChannels)
// Prints "10"
Copyright © 2017 Apple Inc. All rights reserved. Terms of Use | Privacy Policy | Updated: 2017-09-19


Welcome to the CQRS bookstore
Available books:
Book Title
Price
Shopping cart
Cart is empty
Item
Quantity
Price
Clear cart
Order information
Full Name
Address
Email
Place order


Git-it is a desktop application with interactive lessons teaching Git and GitHub basics.
It uses the real terminal (rather than emmulating it) and it uses real Git and GitHub which means when you finish all of the challenges you'll have real repositories on your GitHub account and green squares on your contribution chart! And what you install to complete Git-it (Git and a text editor) is all you need to continue development after you're done—you're set up!
Some challenges require an internet connection, so you'll need to be online order to complete Git-it. But you can always open the app and use the guide and resources offline.
This app is built with HTML, CSS and JS and uses the Electron library. Read more about its development in its documentation (Coming soon!). Git-it repository on GitHub.