This product is made available subject to acceptance of the EPICS open source license.
pvIOCCPP is the C++ implementation of pvIOC, which is one part of the set of related products in the EPICS V4 control system programming environment:
Each of these products has a Java and a C++ implementation.
The products are all part of the V4 implementation of Experimental Physics and Industrial Control System (EPICS).
This is the 18-Oct-2012 version of the C++ implementation of pvIOC. This release implements only the following:
The following is a list of unresolved issues for pvIOCCPP:
pvIOCCPP is one of a set of related projects. This project uses projects pvDataCPP and pvAccessCPP. It is assumed that the reader is familar with these projects.
At the present time the only parts of pvIOCCP that are implemented are:
These are described in this document. Everything else that appears in this project is work in progress.
A complete Java implementation of pvIOC (pvIOCJava) is available but it can not be used inside a V3 IOC.
Doxygen documentation is available at doxygenDoc
Both iocCore and pvIOC are based on the concept of a database of memory resident "smart" records. A record is called smart because code is attached to the record and is triggered by asking the record to process.
CAV3 (channel access version 3), which is a component of iocCore, provides network access to iocCore records. pvAccess provides network access to pvIOC records. Both access a record via the channelName which is just the name of the record and optionally the name of a field in the record. The record name must be unique within the local area network.
This section provides an overview of:
Each of these is discused first for iocCore and then for pvAccess/pvIOC.
For CAV3 a channelName consists of a "recordName.fieldName" The default fieldName is "VAL". The field data has one of the following types:
In addition a field can have some set of the following properties.
CAV3 provides I/O functions that falls into the following classes:
CAV3 provides no way for the client to influence record processing. Puts can cause processing but database access decides if a put causes a record to process.
For pvAccess a channelName consists of just the recordName. How the client specifies what data and options are desired are discussed below. For now just realize that each data item passed between client and server is a via an identical top level pvStructure on each side.
A brief description of a pvStructure is that it is a structure that has a set of PVFields where each field has one of the following types:
Although pvAccess itself does not get involved, pvData defines a set of "standard" PVStructures and assocated code called properties.
Note: pvData and pvAccess are not directly involved with normative types (NT). They merely make it possible to create NT structures.
The currently defined property structures are:
pvAccess provides the following:
When a client connects to a record the client receives an interface Channel. The interface has a create method for each of the above, i.e. createChannelProcess, etc. Each of these create methods has an argument "PVStructure pvRequest". The pvRequest structure is passed from the client to the server. pvAccess itself does not care what is in pvRequest; it is just a top level pvStructure. But a set of conventions exist for communication with a PVIOC. A pvAccess server should follow the same conventions unless it has special requirements.
There is a "convenience" service that, given a string, creates a pvRequest. A simple example is:
pvRequest = createRequest("field(alarm,timeStamp,value)");
The details are provided in pvAccessJava.html. The brief description is that the pvRequest allows the client to specify the following:
pvRequest = createRequest("record[process=true]field(alarm,timeStamp,value)");This asks that the record be processed. There are two standard record options:
A record is a flat structure, i.e. it is a structure that has a set of fields each of which has a name. Each field is one of the following types:
DBF_STRING, DBF_CHAR, DBF_UCHAR, DBF_SHORT, DBF_USHORT, DBF_LONG, DBF_ULONG, DBF_FLOAT, DBF_DOUBLE, DBF_ENUM, DBF_MENU, DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, DBF_FWDLINK, DBF_NOACCESS
DBF_CHAR, ... ,DBF_DOUBLE are the numeric types. The other types are:
A record instance has a record type. Each record type has a fixed set of fields. Each has a common set of 43 fields and a set of record type specific fields. For example ai adds 39 fields and mbbi adds 65 fields. Most of these fields are not of interest to clients. The field of most interest is VAL. Many other fields are properties of the value field. Normally client code does not directly access property fields but gets their values via chnnelAccess. Many fields are private and can not be accessed via channelAccess.
EPICS base provides a set of record types, e. g. ai, ao, bi, bo, etc. It also provides facilities for defining additional record types. Each record type has associated code that is accessed via a rset (Record Support Entry Table):
typedef struct rset { /* record support entry table */ long number; /*number of support routines */ RECSUPFUN report; /*print report */ RECSUPFUN init; /*init support */ RECSUPFUN init_record; /*init record */ RECSUPFUN process; /*process record */ RECSUPFUN special; /*special processing */ RECSUPFUN get_value; /*get value field */ RECSUPFUN cvt_dbaddr; /*cvt dbAddr */ RECSUPFUN get_array_info; RECSUPFUN put_array_info; RECSUPFUN get_units; RECSUPFUN get_precision; RECSUPFUN get_enum_str; /*get string from enum item*/ RECSUPFUN get_enum_strs; /*get all enum strings */ RECSUPFUN put_enum_str; /*put string from enum item*/ RECSUPFUN get_graphic_double; RECSUPFUN get_control_double; RECSUPFUN get_alarm_double; }rset;
These method are called by dbAccess, which is major component of iocCore. Method process is called to process the record. The details are determined by the record suport. The methods get_value, ... ,get_alarm_double are all related to the field named VAL. get_array_info and put_array_info apply if the value field is an array. get_enum_str ,..., put_enum_str apply if value is an enumerated field. The other get_xxx methods get properties of the value field.
Three fields from dbCommon releted to record processing are SCAN,FLNK, and DTYP. Many record types have either a field INPUT or OUTPUT.
Because processing a record can cause linked records to also be processed, the concept of scan set exists. Before a record is processed a function dbScanLock is called and when it completes processing dbScanUnlock is called. All records linked together directly or indirectly are placed in the same lock set. When dbScanLock is called the entire set, not just the specified record, is locked. This prevents two different tasks from simultaneously modifying records in the same lock set.
Device support can be either synchronous or asynchronous. A synchronous record is a record where device support can complete without wait for I/O. Asynchronous support is support that needs to wait. Asynchonous processing consists of two two phases: process start and process completion. Between the two phases the record is unlocked.
NOTE: currently record and record processing is only impelemented by pvIOCJava.
A PVRecord has a top level PVStructure. Thus the data layout is just PVData. As mentioned above pvData defines standard structures and support for enumerated, alarm, timeStamp, display, control, and valueAlarm.
pvIOC has the the same processing features as V3IOC. The main difference are:
The interface for support is:
interface Support { void initialize(); void start(AfterStart afterStart); void stop(); void uninitialize(); void process(SupportProcessRequester supportProcessRequester); }
Although record types do not exist there are standards for field layout so that the equivalent of the V3IOC ai, ao, etc records can be created.
Support is provided that implements database and channelAccess links.
The status of interoperability between V3 and pvIOC/pvAccess is:
From the point of view of a pvAccess client.
A CAV3 client has access to a channel that is a PVRecord only if the record is on a pvIOCJava.
What is currently implemented by pvIOCCPP has almost non of the features a pvIOC is expected to provide. The documentation for pvIOCJava descibes what a full implementation provides.
Other then service and ezchannelRPC, which should be moved to pvAccessCPP, the only things pvIOCCPP currently provides are v3Channel, channelProviderLocal, and multiChannel.
v3Channel, which is a channelProvider for V3 records, is quite usedful and should remain a feature.
channelProviderLocal provides a framework for a channelProvider with the name local. It is a very weak version of pvIOCJava implements. It provides a pvAccess context and allows code to register channelProvider instances. BUT each instance must itself implement ChannelProvider and Channel. To fully implement Channel take a lot of code unless pvIOC provides help.
At present the only Channel implementations in pvIOCCPP are v3Channel and multiChannel.
v3Channel implements a pvAccess server for accessing V3 records. It implements everything that makes sense for V3 records.
multiChannel implements Channel and ChannelGet. Each instance provides a channel that holds data from a set of channels obtained from another channelProvider. But multiChannel is very limited. It currently only implements channelGet, only returns the complete set of data that the instance is configured to collect, and acts like every data value changed on every get request.
What is required is a much more. The following discusses a phased implementation to a full implementation of what a pvIOC should provide:
The minimum features will allow a full implementation of Channel but will require code for each type of functionality desired. In addition there will only be a single support for a record instance.
With the minimum features a complete Channel implementation for multiChannel is possible.
The minimum set of features is:
This phase adds the ability to optionally add support to any field of a record. This phase includes the set of basic support that pvIOCJava implements. This phase still requires code to create each record and register it with channelProvider.
This phase requires:
This provides access to all the support provided by asynDriver which is huge.
This provides a database and on-line add and remove records. It still requires code to create record instances.
This provides the ability to create records without writing code.
This is a replacement for the asynManger component of asynDriver. See the implementation in pvIOCJava for details.
V3Channel provides access to V3 records. It can be used by other code in the same IOC or by pvAccess network clients via remote pvAccess. It implements channelProcess, channelGet, channelPut, channelArray, and Monitor. It does not implement channelPutGet or channelRPC since, at least for now, these do not apply to V3 records.
Because V3 records have a flat record structure the top level structure the pvAccess client sees also has a "flat" structure. The exception is that alarm, timeStamp, display, control, and valueAlarm appear as the pvData property structures. For example an ai record will appear as:
mrk> pvget -r "field()" double01 double01 uri:ev4:nt/2012/pwd:NTScalar double value 0 alarm_t alarm int severity 3 int status 0 string message UDF time_t timeStamp long secondsPastEpoch 631152000 int nanoSeconds 0 int userTag 0 display_t display double limitLow 0 double limitHigh 10 string description string format %f string units Counts control_t control double limitLow -0.1 double limitHigh 9.9 double minStep 0 valueAlarm_t valueAlarm boolean active false double lowAlarmLimit 2 double lowWarningLimit 4 double highWarningLimit 6 double highAlarmLimit 8 int lowAlarmSeverity 0 int lowWarningSeverity 0 int highWarningSeverity 0 int highAlarmSeverity 0 double hystersis 0 mrk>
The basic idea is to map what V3 records provide into a PVStruructure that has the same information. For example if a client makes the following request:
pvget -r "field()" quadruple:BField
The result is:
scalar_t double value 0 alarm_t alarm int severity 3 int status 0 string message UDF timeStamp_t timeStamp long secondsPastEpoch 631152000 int nanoSeconds 0 int userTag 0 display_t display double limitLow 0 double limitHigh 10 string description string format %f string units tesla control_t control double limitLow 0 double limitHigh 10 double minStep 0 valueAlarm_t valueAlarm boolean active false double lowAlarmLimit 2 double lowWarningLimit 4 double highWarningLimit 6 double highAlarmLimit 8 int lowAlarmSeverity 0 int lowWarningSeverity 0 int highWarningSeverity 0 int highAlarmSeverity 0 double hystersis 0
The channelName can be either just a record name or a "recordName.XXX" where XXX is the V3 field name, e. g. "SCAN".
NOTE: pvIOCCP has a iocBoot directory structure like any V3 application. To see an example do the following:
In one window:
mrk> pwd /home/mrk/hg/pvIOCCPP/iocBoot/simpleV3Channel mrk>../../bin/linux-x86_64/simpleV3Channel st.cmd
In another window:
mrk> pvget -r "field()" TESTDOUBLE
pvIOCCPP runs in a regular V3 IOC as defined by EPICS base. It uses the base build system and is built as an EPICS application. To use V3Channel do the following:
PVBASE=/home/mrk/hg PVDATA=${PVBASE}/pvDataCPP PVACCESS=${PVBASE}/pvAccessCPP PVIOC=${PVBASE}/pvIOCCPP
include "base.dbd" include "v3Channel.dbd"
startV3Channel
NOTE: Most readers can skip this section.
This section is only of interest to someone who wants to understand the internals of v3Channel. Because v3Channel transfers data between pvData and V3 records it is complex. To understand it requires a knowledge of the internals of the V3 database and of pvData.
The implementation consists of the following header files:
Associated with each header file is a corresponding implementation file which has the same file name as the header but with an extension of ".cpp". The remainder of this section gives a brief description of each of these software components with an emphasis on how data is converted between pvData and data in V3 records.
In epics V3 there are two interfaces for accessing data:
This defines two interfaces:
V3ChannelProvider is defined as:
class V3ChannelProvider : public epics::pvAccess::ChannelBaseProvider { public: POINTER_DEFINITIONS(V3ChannelProvider); static V3ChannelProviderPtr getV3ChannelProvider(); virtual ~V3ChannelProvider(); virtual ChannelFind::shared_pointer channelFind( String const &channelName, ChannelFindRequester::shared_pointer const & channelFindRequester); virtual Channel::shared_pointer createChannel( String const &channelName, ChannelRequester::shared_pointer const &channelRequester, short priority, String const &address); private: }
where
V3Channel is defined as:
class V3Channel : public virtual epics::pvAccess::ChannelBase { public: POINTER_DEFINITIONS(V3Channel); V3Channel( gChannelBaseProvider::shared_pointer const & channelProvider, gChannelRequester::shared_pointer const & requester, gString const & name, std::auto_ptraddr ); virtual ~V3Channel(); void init(); virtual void getField( gGetFieldRequester::shared_pointer const &requester, gString const &subField); virtual gChannelProcess::shared_pointer createChannelProcess( gChannelProcessRequester::shared_pointer const &channelProcessRequester, gPVStructure::shared_pointer const &pvRequest); virtual gChannelGet::shared_pointer createChannelGet( gChannelGetRequester::shared_pointer const &channelGetRequester, gPVStructure::shared_pointer const &pvRequest); virtual gChannelPut::shared_pointer createChannelPut( gChannelPutRequester::shared_pointer const &channelPutRequester, gPVStructure::shared_pointer const &pvRequest); virtual gMonitor::shared_pointer createMonitor( gMonitorRequester::shared_pointer const &monitorRequester, gPVStructure::shared_pointer const &pvRequest); virtual gChannelArray::shared_pointer createChannelArray( gChannelArrayRequester::shared_pointer const &channelArrayRequester, gPVStructure::shared_pointer const &pvRequest); virtual void printInfo(); virtual void printInfo(StringBuilder out); private: ... }
where
This does most of the work related to transfering data between a PVStructure and a V3 record. All methods are static and are called by V3ChannelGet, V3ChannelPut, etc. Each first calls getProperty which returns a mask that is passed to the other methods. The mask bits show a combination of what the requester requested and characteristics of the V3 field being accessed. The mask has the following bits:
V3Util is defined as:
class V3Util { public: POINTER_DEFINITIONS(V3Util); virtual ~V3Util() {} static V3UtilPtr getV3Util(); // client request bits int processBit; // is processing requested int shareArrayBit; // share V3array instead of copy int timeStampBit; // get timeStamp; int alarmBit; // get alarm int displayBit; // get display info int controlBit; // get control info int valueAlarmBit; // get value alarm info // V3 data characteristics int scalarValueBit; // value is a scalar int arrayValueBit; // value is an array int enumValueBit; // value is an enum int noAccessBit; // fields can not be accessed int noModBit; // fields can not be modified int dbPutBit; // Must call dbPutField int isLinkBit; // field is a DBF_XXLINK field int getProperties( gRequester::shared_pointer const &requester, gPVStructure::shared_pointer const &pvRequest, DbAddr &dbAddr, bool processDefault); gPVStructurePtr createPVStructure( gRequester::shared_pointer const &requester, int mask,DbAddr &dbAddr); void getPropertyData( gRequester::shared_pointer const &requester, int mask,DbAddr &dbAddr, gPVStructurePtr const &pvStructure); gStatus get( gRequester::shared_pointer const &requester, int mask,DbAddr &dbAddr, gPVStructurePtr const &pvStructure, gBitSet::shared_pointer const &bitSet, CAV3Data *caV3Data); gStatus put( gRequester::shared_pointer const &requester, int mask,DbAddr &dbAddr, gPVFieldPtr const &pvField); gStatus putField( gRequester::shared_pointer const &requester, int mask,DbAddr &dbAddr, gPVFieldPtr const &pvField); gScalarType getScalarType( gRequester::shared_pointer const &requester, DbAddr &dbAddr); private: ... }
where
This creates special implementations of PVByteArray, ... , PVStringArray that access the corresponding array types in the V3 record. Except for PVStringArray it provides the ability to share data instead of making copies. It gets and puts array lengths via the V3 record support entry table methods. Note that it has speciaized methods for all of get, put, serialize, and deserialize that are not provided by PVDataCreate.
V3Array is defined as:
class V3ValueArrayCreate { public: POINTER_DEFINITIONS(V3ValueArrayCreate); gPVByteArrayPtr createByteArray( gPVStructurePtr const & parent, gScalarArrayConstPtr const & scalar, DbAddr &dbAddr,bool shareData); gPVUByteArrayPtr createUByteArray( gPVStructurePtr const & parent, gScalarArrayConstPtr const & scalar, DbAddr &dbAddr,bool shareData); gPVShortArrayPtr createShortArray( gPVStructurePtr const & parent, gScalarArrayConstPtr const & scalar, DbAddr &dbAddr,bool shareData); gPVUShortArrayPtr createUShortArray( gPVStructurePtr const & parent, gScalarArrayConstPtr const & scalar, DbAddr &dbAddr,bool shareData); gPVIntArrayPtr createIntArray( gPVStructurePtr const & parent, gScalarArrayConstPtr const & scalar, DbAddr &dbAddr,bool shareData); gPVUIntArrayPtr createUIntArray( gPVStructurePtr const & parent, gScalarArrayConstPtr const & scalar, DbAddr &dbAddr,bool shareData); gPVFloatArrayPtr createFloatArray( gPVStructurePtr const & parent, gScalarArrayConstPtr const & scalar, DbAddr &dbAddr,bool shareData); gPVDoubleArrayPtr createDoubleArray( gPVStructurePtr const & parent, gScalarArrayConstPtr const & scalar, DbAddr &dbAddr,bool shareData); // Note that V3StringArray can not share gPVStringArrayPtr createStringArray( gPVStructurePtr const & parent, gScalarArrayConstPtr const & scalar, DbAddr &dbAddr); }; typedef std::tr1::shared_ptrV3ValueArrayCreatePtr; extern V3ValueArrayCreatePtr getV3ValueArrayCreate();
where
In V3 dbEvent is what implements db_post_event, which is what is called when a field value changes in a V3 record. But dbEvent just passes this to V3CA. Thus the only way to trap V3 monitors is via a call to ca_create_subscription. The implementation takes only the following from the CAV3 event callback: scalar value, alarm status and sererity, and the timeStamp. All other data, e.g. array values, are taken from the record as a result of the CAV3 event callback.
V3CAMonitor provides an enum that describes the data type of a V3 field as seen by pvData.
enum V3Type { v3Enum, v3Byte, v3UByte, v3Short, v3UShort, v3Int, v3UInt, v3Float, v3Double, v3String };
where
Next a C structure is defined in which data from CAV3 is put. Each time CAV3 calls the event callback the CAV3 data is copied to this structure.
struct CAV3Data { CAV3Data(); ~CAV3Data(); /* The following have new values after each data event*/ union { //only used for scalar values int8 byteValue; uint8 ubyteValue; uint16 ushortValue; int16 shortValue; int32 intValue; uint32 uintValue; float floatValue; double doubleValue; }; epicsTimeStamp timeStamp; int sevr; int stat; const char * status; };
where
Next is an interface that provides c++ callbacks that can be called by the C callbacks that CAV3 calls:
class CAV3MonitorRequester : public virtual Requester { public: POINTER_DEFINITIONS(CAV3MonitorRequester); virtual ~CAV3MonitorRequester(){} virtual void exceptionCallback(long status,long op) = 0; virtual void connectionCallback() = 0; virtual void accessRightsCallback() = 0; virtual void eventCallback(const char *status) = 0;
where
Finally the interface for CAV3Monitor:
class CAV3Monitor : private epics::pvData::NoDefaultMethods { public: CAV3Monitor( CAV3MonitorRequesterPtr const &requester, epics::pvData::String const &pvName, V3Type v3Type); ~CAV3Monitor(); CAV3Data & getData(); void connect(); void start(); void stop(); const char * getStatusString(long status); bool hasReadAccess(); bool hasWriteAccess(); bool isConnected(); private: ... }
where
CAV3Monitor calls CAV3 in order to monitor changes to the V3 records. In order to do this it must call ca_context_create(ca_enable_preemptive_callback). It must call this from the thread that wil make calls to CAV3. But it must also call ca_attach_context from any other threads associated with the thread that calls ca_context_create. The putpose of CAV3Context is to manage this interaction with CAV3.
:1,$s/For each thread that V3Channel uses and that makes a CreateMonitor CAV3Context keeps a reference count. This is decremented when CAV3Contect::release is called, which is done when a V3CAMonitor is deleted. Only when the thread that originally resulted in a CAV3Context exits is the CAV3Context deleted. Thus if a single client connects to several V3 records each instance of V3Channel and all ChannelGets, etc. for that channel share the same context.:q
CAV3Context is defined as:
class CAV3Context { public: POINTER_DEFINITIONS(CAV3Context); ~CAV3Context(); void release(); void stop(); void exception(String const &message); void checkContext(); private: ... };
where
There is a separate class for creating a context:
lass CAV3ContextCreate { public: static CAV3ContextPtr get(epics::pvData::RequesterPtr const & requester); private: ... }
where
This implements a channelProvider named "local" intended for use by code that wants to make data available to pvAccess clients. It has the following features:
To start localChannel provider the XXXInclude.dbd file used to build the application must include the following:
include "channelProviderLocal.dbd"
The st.cmd file that starts the IOC must have the statement:
startChannelProviderLocal
Code that provides data via a top level PVStructure has code like:
ChannelAccess::shared_pointer channelAccess = getChannelAccess(); ChannelProvider::shared_pointer channelProvider = channelAccess->getProvider("local"); ChannelProviderLocalPtr channelProviderLocal = static_pointer_cast<ChannelProviderLocal>(channelProvider); channelProviderLocal->registerProvider(channelName,provider);
The only method of interest to code that provides data via a top level PVStructure is:
ChannelProviderLocalPtr channelProviderLocal = static_pointer_cast<ChannelProviderLocal>(channelProvider); channelProviderLocal->registerProvider(channelName,provider);
To see an example of multiChannel start the following IOC:
mrk> pwd /home/mrk/hg/pvIOCCPP/iocBoot/testMultiValue mrk> ../../bin/linux-x86_64/testMultiValue st.cmd
A dbl command shows the following V3 records are present:
epics> dbl quadruple:BField quadruple:Current quadruple:POLYNOMIAL
Then in another window:
mrk> pwd /home/mrk/hg/pvIOCCPP/iocBoot/testMultiValue mrk> source clientTest
The file clientTest contains:
pvput quadruple:BField 1 pvput quadruple:Current 5 pvput quadruple:POLYNOMIAL 1,2,3,4,5 pvget quadruple
You should see:
Old : scalar_t double value 0 New : scalar_t double value 1 Old : scalar_t double value 0 New : scalar_t double value 5 Old : structure double[] value [] New : structure double[] value [1,2,3,4,5] structure alarm_t alarm int severity 3 int status 0 string message UDF timeStamp_t timeStamp long secondsPastEpoch<PHONE_NUMBER> int nanoSeconds 368066848 int userTag 0 double bfield 1 double current 5 double[] conversionPolynomial [1,2,3,4,5]
MultiValue provides support for creating pvAccess channels that are made available via channelProviderLocal. Each channel holds data from the value fields of a set of channels provided by another channel provider. A primary use is the collect data from a set of V3 records in the same IOC.
Each channel has a top level structure that has an alarm and timeStamp field. In addition there is a field for each value field obtained from the other channel provider.
iocBoot/testMultiValue provides an example of how multiChannel is used.
The V3 database that is loaded is:
record(waveform, "quadruple:POLYNOMIAL") {...} record(ai, "quadruple:Current") {...} record(ai, "quadruple:BField") {...}
The st.cmd file ends with:
createMultiValueChannel quadrupole.txt
The field quadrupole.txt contains:
channelValueProvider v3Channel channelName quadrupole channelValue bfield quadrupole:BField current quadrupole:Current conversionPolynomial quadrupole:POLYNOMIAL
This says to create a pvAccess channel with channelName quadrupole. The channel provider for the data fields is v3Channel, i.e. the provider that accesses V3 records.
The command:
pvget -r "field()" quadrupole
will return the following structure:
structure alarm_t alarm int severity 3 int status 0 string message UDF timeStamp_t timeStamp long secondsPastEpoch<PHONE_NUMBER> int nanoSeconds 832012665 int userTag 0 double bfield 1 double current 5 double[] conversionPolynomial [1,2,3,4,5]
Look at pvIOCCPP/testApp/testMultiValue for an example of how to create an application that uses the multiChannel support. Look at pvIOCCPP/iocBoot/testMultiValue for an example of how to create a multiChannel instance. The st.cmd file ends with: createMultiValue quadruple.txt
This creates a multiChannel channel defined by file quadruple.txt which contains:
channelValueProvider v3Channel channelName quadruple channelValue bfield quadruple:BField current quadruple:Current conversionPolynomial quadruple:POLYNOMIAL
Files createMultiValue.dbd and createMultiValueRegister.cpp are what registers and implements the iocshell command createMultiValue.
The syntax accepted by createMultiVaue is:
channelValueProvider channelProvider channelName name channelValue fieldName channelName ...
This file describes the classes MultiValueChannelProvider, MultiValueChannel, and MultiValueChannelGet. It is only of interest it You want to understand the code. If so look at the code.
This is a wrapper for accessing a channel. It provides a synchronous interface for accessing a channel. It currently only provides support for channelGet. When EasyPVA is available it will not be needed.
This is support code for developing network based services that use pvAccess as the network protocol. In particular the server side of a pvAccess service.
Service provides support for the following:
Except for the RPC support, this code is only present because pvIOCCPP does not implement a pvIOC database, support, etc. When these are created the code should disappear.
class ServiceRPC { public: POINTER_DEFINITIONS(ServiceRPC); virtual void destroy() = 0; virtual void request( ChannelRPCRequester::shared_pointer const & channelRPCRequester, PVStructure::shared_pointer const & pvArgument) = 0; }; class ServiceChannelRPC : public std::tr1::enable_shared_from_this<ServiceChannelRPC> { public: POINTER_DEFINITIONS(ServiceChannelRPC); ServiceChannelRPC(i String const &channelName, ServiceRPC::shared_pointer const & serviceRPC); virtual ~ServiceChannelRPC(); virtual void destroy(); private: ... };
ServiceRPC is the class the service must implement. It has the methods:
ServiceChannelRPC is a class that implements the server side of channelRPC. It will call ServiceRPC when a client issues a channelRPC request. It takes care of all other pvAccess requirements. It has the methods:
This is the header file for code that implements two classes: ChannelBaseProvider and ChannelBase. Each is discussed separately.
NOTE: A service that implements only ChannelRPC can ignore this section.
channelBaseProvider takes care of "lifetime" issues. It registers the provider, keeps a list of all channels the service provider creates and destroys all channels when the provider is destroyed.
class ChannelBaseProvider : public ChannelProvider, public std::tr1::enable_shared_from_this{ public: POINTER_DEFINITIONS(ChannelBaseProvider); ChannelBaseProvider( String const &providerName ); virtual ~ChannelBaseProvider(); virtual String getProviderName(); virtual void destroy(); virtual ChannelFind::shared_pointer channelFind( String const & channelName, ChannelFindRequester::shared_pointer const & channelFindRequester) = 0; virtual Channel::shared_pointer createChannel( String const & channelName, ChannelRequester::shared_pointer const &requester, short priority); virtual Channel::shared_pointer createChannel( String const & channelName, ChannelRequester::shared_pointer const & channelRequester, short priority, String const & address) = 0; // following called by derived class void channelFound( bool found, ChannelFindRequester::shared_pointer const & requester); void channelNotCreated( ChannelRequester::shared_pointer const & requester); void channelCreated(ChannelBase::shared_pointer const &channel); void removeChannel(ChannelBase::shared_pointer const &channel); void unregisterSelf(); void registerSelf(); protected: ... }
The service must implement the following two ChannelProvider methods:
channelBaseProvider implements the following methods:
This implements all the Channel methods. This a service only needs the implement the methods it supports. For example a service may only implement ChannelGet and ChannelPut. In that case it only needs to implement the createChannelGet and createChannelPut methods of Channel as well as ChannelGet and ChannelPut.
class ChannelBase : public virtual Channel, public std::tr1::enable_shared_from_this<ChannelBase> { public: POINTER_DEFINITIONS(ChannelBase); ChannelBase( ChannelProvider::shared_pointer const &channelProvider, ChannelRequester::shared_pointer const & requester, String const & channelName ); virtual ~ChannelBase(); virtual void destroy(); virtual String getRequesterName(); virtual void message( String const & message, MessageType messageType); virtual ChannelProvider::shared_pointer const & getProvider(); virtual String getRemoteAddress(); virtual Channel::ConnectionState getConnectionState(); virtual String getChannelName(); virtual ChannelRequester::shared_pointer const & getChannelRequester(); virtual bool isConnected(); virtual void getField( GetFieldRequester::shared_pointer const &requester, String const & subField); virtual AccessRights getAccessRights( PVField::shared_pointer const &pvField); virtual ChannelProcess::shared_pointer createChannelProcess( ChannelProcessRequester::shared_pointer const &requester, PVStructure::shared_pointer const &pvRequest); virtual ChannelGet::shared_pointer createChannelGet( ChannelGetRequester::shared_pointer const &requester, PVStructure::shared_pointer const &pvRequest); virtual ChannelPut::shared_pointer createChannelPut( ChannelPutRequester::shared_pointer const &requester, PVStructure::shared_pointer const &pvRequest); virtual ChannelPutGet::shared_pointer createChannelPutGet( ChannelPutGetRequester::shared_pointer const &requester, PVStructure::shared_pointer const &pvRequest); virtual ChannelRPC::shared_pointer createChannelRPC( ChannelRPCRequester::shared_pointer const &requester, PVStructure::shared_pointer const &pvRequest); virtual Monitor::shared_pointer createMonitor( MonitorRequester::shared_pointer const &requester, PVStructure::shared_pointer const &pvRequest); virtual ChannelArray::shared_pointer createChannelArray( ChannelArrayRequester::shared_pointer const &requester, PVStructure::shared_pointer const &pvRequest); virtual void printInfo(); virtual void printInfo(StringBuilder out); // following called by derived classes void addChannelProcess(ChannelProcess::shared_pointer const &); void addChannelGet(ChannelGet::shared_pointer const &); void addChannelPut(ChannelPut::shared_pointer const &); void addChannelPutGet(ChannelPutGet::shared_pointer const &); void addChannelMonitor(Monitor::shared_pointer const &); void addChannelRPC(ChannelRPC::shared_pointer const &); void addChannelArray(ChannelArray::shared_pointer const &); void removeChannelProcess(ChannelProcess::shared_pointer const &); void removeChannelGet(ChannelGet::shared_pointer const &); void removeChannelPut(ChannelPut::shared_pointer const &); void removeChannelPutGet(ChannelPutGet::shared_pointer const &); void removeChannelMonitor(Monitor::shared_pointer const &); void removeChannelRPC(ChannelRPC::shared_pointer const &); void removeChannelArray(ChannelArray::shared_pointer const &); };
The service only needs to implement the set of create methods that it supports. For each the service must also implement the associated ChannelXXX interfaces. The service may also want to implement the printInfo methods.
ChannelBase implements the following methods:
NOTE: A service that implements only ChannelRPC can ignore this section except for PVServiceChannelCTX.
This describes three classes: ServicePVTop, PVServiceProvider, and PVServiceChannelCTX. Each will be discussed separately.
This is the class that a service provider must implement.
class ServicePVTop { public: POINTER_DEFINITIONS(ServicePVTop); virtual ~ServicePVTop(){} virtual String getName() = 0; virtual ChannelBase::shared_pointer createChannel( ChannelRequester::shared_pointer const &requester, std::tr1::shared_ptr<PVServiceProvider> const &provider) = 0; virtual void destroy() = 0; };
where
This is a complete implementation of ChannelProvider. There is a single instance. The code that uses it must implement interface ServicePVTop. The code must also create a top level PVStructure, which is what the pvAccess client will access. PVServiceProvider has methods:
Each takes an argument ServicePVTop.
This is for use by services that want to run as a standalone service, i. e. not as part on a V3 IOC. It starts the remote server for pvAccess. See testApp/exampleServiceRPC/exampleServiceRPCMain.cpp for an example of how to start it.
This is pvAccess client code for making a ChannelRPC request. An effort is being started to develop an easy to use interface to pvAccess. When this facility is available something like ezchannelRPC will be part of it.
In order to make the example simpler there is also code that implement an easy to use interface to channelRPC.
class EZChannelRPC : public ChannelRequester, public ChannelRPCRequester, public std::tr1::enable_shared_from_this<EZChannelRPC> { public: POINTER_DEFINITIONS(EZChannelRPC); EZChannelRPC( epics::pvData::String const &channelName); EZChannelRPC( epics::pvData::String const &channelName, epics::pvData::PVStructure::shared_pointer pvRequest); virtual ~EZChannelRPC(); void destroy(); bool connect(double timeout); void issueConnect(); bool waitConnect(double timeout); epics::pvData::PVStructure::shared_pointer request( epics::pvData::PVStructure::shared_pointer const & pvArgument, bool lastRequest); void issueRequest( epics::pvData::PVStructure::shared_pointer const & pvArgument, bool lastRequest); epics::pvData::PVStructure::shared_pointer waitRequest(); epics::pvData::String getMessage(); ... }
where
Currently the only C++ support for services is support for channelRPC, i. e. support for services where the client and server communicate via pvAccess::channelRPC. In the near future support is planned for for channelPutGet.
There is an example service in testApp/exampleServiceRPC. This example can be run either as a main program or as part of V3 IOC using the v3Channel support described in the next section. To run it as a main program just execute the command:
bin/<arch>/exampleServiceRPC
To execute it as part of a V3 IOC do the following:
cd iocBoot/testV3Channel ../../bin/<arch>/testV3Channel st.cmd
Once the example service is running the example client can be executed, in another window, via the command:
bin/<arch>/exampleClient
The example is in testApp/exampleServiceRPC.
exampleServiceRPC.h contains:
class ExampleServiceRPC : public virtual ServiceRPC, public std::tr1::enable_shared_from_this<ExampleServiceRPC> { public: POINTER_DEFINITIONS(ExampleServiceRPC); ExampleServiceRPC(); virtual ~ExampleServiceRPC(); virtual void destroy(); virtual void request( epics::pvAccess::ChannelRPCRequester::shared_pointer const & channelRPCRequester, epics::pvData::PVStructure::shared_pointer const & pvArgument); private: ExampleServiceRPC::shared_pointer getPtrSelf() { return shared_from_this(); } };
This just shows how the example extends ServiceRPC. All services should have a similar definition except for the name, i. e. replace ExampleService with some other name.
The implementation is in exampleServiceRPC.cpp:
ExampleServiceRPC::ExampleServiceRPC(){} ExampleServiceRPC::~ExampleServiceRPC(){} void ExampleServiceRPC::destroy(){} void ExampleServiceRPC::request( ChannelRPCRequester::shared_pointer const & channelRPCRequester, epics::pvData::PVStructure::shared_pointer const & pvArgument) { String buffer; PVStringPtr pvfunction = pvArgument->getStringField("function"); PVStringArrayPtr pvnames = static_pointer_cast<PVStringArray> (pvArgument->getScalarArrayField("names",pvString)); PVStringArrayPtr pvvalues = static_pointer_cast<PVStringArray> (pvArgument->getScalarArrayField("values",pvString)); buffer += "pvArgument "; bool is = true; if(pvfunction==0) is = false; if(pvnames==0) is = false; if(pvvalues==0) is = false; if(is) { buffer += "is a NTNameValue\n"; } else { buffer += "is not a NTNameValue\n "; } pvArgument->toString(&buffer); printf("%s\n",buffer.c_str()); StandardFieldPtr standardField = getStandardField(); StandardPVFieldPtr standardPVField = getStandardPVField(); FieldCreatePtr fieldCreate = getFieldCreate(); PVDataCreatePtr pvDataCreate = getPVDataCreate(); size_t n = 5; FieldConstPtrArray fields; StringArray names; fields.reserve(n); names.reserve(n); names.push_back("alarm"); names.push_back("timeStamp"); names.push_back("label"); names.push_back("position"); names.push_back("alarms"); fields.push_back(standardField->alarm()); fields.push_back(standardField->timeStamp()); fields.push_back(fieldCreate->createScalarArray(pvString)); fields.push_back(fieldCreate->createScalarArray(pvDouble)); fields.push_back(fieldCreate->createStructureArray(standardField->alarm())); StructureConstPtr structure = fieldCreate->createStructure(names,fields); PVStructurePtr pvStructure = pvDataCreate->createPVStructure(structure); PVTimeStamp pvTimeStamp; TimeStamp timeStamp; pvTimeStamp.attach(pvStructure->getStructureField("timeStamp")); timeStamp.getCurrent(); pvTimeStamp.set(timeStamp); StringArray label; label.reserve(2); for(int i=0; i<2; i++) { label.push_back(names[i+3]); } PVStringArrayPtr pvLabel = static_pointer_cast<PVStringArray> (pvStructure->getScalarArrayField("label",pvString)); pvLabel->put(0,2,label,0); PVDoubleArrayPtr pvPositions = static_pointer_cast<PVDoubleArray> (pvStructure->getScalarArrayField("position",pvDouble)); double positions[2]; positions[0] = 1.0; positions[1] = 2.0; pvPositions->put(0,2,positions,0); PVStructureArrayPtr pvAlarms = static_pointer_cast<PVStructureArray> (pvStructure->getStructureArrayField("alarms")); PVAlarm pvAlarm; Alarm alarm; PVStructurePtrArray palarms; size_t na=2; palarms.reserve(na); for(size_t i=0; i<na; i++) { palarms.push_back(pvDataCreate->createPVStructure(standardField->alarm())); } for(size_t i=0; i<na; i++) { pvAlarm.attach(palarms[i]); alarm.setMessage("test"); alarm.setSeverity(majorAlarm); alarm.setStatus(clientStatus); pvAlarm.set(alarm); } pvAlarms->put(0,2,palarms,0); String labels[2]; labels[0] = pvPositions->getFieldName(); labels[1] = pvAlarms->getFieldName(); pvLabel->put(0,2,labels,0); buffer.clear(); pvStructure->toString(&buffer); printf("%s\n",buffer.c_str()); channelRPCRequester->requestDone(Status::OK,pvStructure); }
The only interesting method is request. The example first looks to see if the argument has the following fields
The idea is that the client passes a function name and a set of name,value pairs as arguments,
The example creates a structure that represents a table. It has fields:
This structure is returned to the client. Note that channelRPCRequester->requestDone(Status::Ok,pvStructure) must be called.
The Make file shows how to build as both a standalone application as as part of a V3 IOC.\
exampleServiceRPCMain.cpp is the main program for a standalone application.
void example() { PVServiceChannelCTX::shared_pointer myCTX = PVServiceChannelCTX::shared_pointer(new PVServiceChannelCTX()); ExampleServiceRPC::shared_pointer example = ExampleServiceRPC::shared_pointer(new ExampleServiceRPC()); ServiceChannelRPC::shared_pointer serviceChannelRPC = ServiceChannelRPC::shared_pointer( new ServiceChannelRPC("serviceRPC",example)); cout << "serviceRPC\n"; string str; while(true) { cout << "Type exit to stop: \n"; getline(cin,str); if(str.compare("exit")==0) break; } } int main(int argc,char *argv[]) { example(); return 0; }
The first statement MUST be present. It starts the pvAccess server. The second statement creates the service. The next statement is what installs the service. The remaining statements just wait for the request to terminate the main program. Except for "ExampleService" any service should have similar code.
exampleServiceRegister.dbd and exampleServiceRegister.cpp are required to run the service as part os a V3 IOC. The dbd file is:
registrar("startExampleServiceRegister")
This is the dbd statement that will have the V3 IOC register the code desctribed in the next file:
The cpp file is:
/* define arguments for the following command: * startExampleService channelName */ static const iocshArg startExampleServiceArg0 = {"channelName", iocshArgString}; static const iocshArg *const startExampleServiceArgs[] = { &startExampleServiceArg0}; static const iocshFuncDef startExampleServiceFuncDef = { "startExampleService", 1, startExampleServiceArgs}; static void startExampleService(const iocshArgBuf *args) { // the channel name is the single argument which is a string const char * channelName = args[0].sval; if(channelName==0 || channelName[0]==0) { printf("illegal channelName\n"); return; } ExampleServiceRPC::shared_pointer example = ExampleServiceRPC::shared_pointer(new ExampleServiceRPC()); ServiceChannelRPC *serviceChannelRPC = new ServiceChannelRPC("serviceRPC",example); } static void startExampleServiceRegister(void) { static int firstTime = 1; if (firstTime) { firstTime = 0; iocshRegister(&startExampleServiceFuncDef, startExampleService); } } epicsExportRegistrar(startExampleServiceRegister);
Again any service can provide similar code. Just change ExampleService to something else.
An example client that calls the exampleServerRPC is also in pvIOCCPP/testApp/exampleServiceRPC.
The client code uses the ezchanelRPC support discussed in a previous section.
The code for the client example is in pvIOCCPP/testApp/exampleServiceRPC/exampleClient.cpp.


public abstract class MASDevice
extends java.lang.Object
The MASDevice class is a local representation of device data.
| Modifier and Type | Method and Description |
|---|---|
void |
addAttribute(java.lang.String attr,
java.lang.String value,
MASCallback<java.lang.Void> callback)
Create or update a new attribute for the current device,
throw MASDeviceAttributeOverflowException when exceed maximum attribute allowed.
|
abstract void |
deregister(MASCallback<java.lang.Void> callback)
Deregisters the application resources on this device.
|
void |
getAttribute(java.lang.String attr,
MASCallback<org.json.JSONObject> callback)
Get attribute by name, return empty JSONObject if no attribute is found.
|
void |
getAttributes(MASCallback<org.json.JSONArray> callback)
Get all attributes, return empty JSONArray if no attributes found.
|
static MASDevice |
getCurrentDevice() |
abstract java.lang.String |
getIdentifier()
The MASDevice identifier.
|
abstract boolean |
isRegistered()
Is the MASDevice registered?
|
void |
removeAllAttributes(MASCallback<java.lang.Void> callback)
Remove all attributes for the current device
|
void |
removeAttribute(java.lang.String attr,
MASCallback<java.lang.Void> callback)
Remove attribute by name, succeed even device attribute does not exists
|
abstract void |
resetLocally()
Resets the application's locally stored data on the device only.
|
abstract void |
startAsBluetoothPeripheral(MASProximityLoginBLEPeripheralListener listener)
This method is used by a device to start a BLE session sharing in a peripheral role.
|
abstract void |
stopAsBluetoothPeripheral()
Stops the device acting as a bluetooth peripheral.
|
public abstract void deregister(MASCallback<java.lang.Void> callback)
Deregisters the application resources on this device. This is a two step operation.
It will attempt to remove the device's registered record in the cloud, and wipe the device of all credential settings. If it fails, an error is returned.
WARNING #1:
A call to deregister during the same session that the device was initially registered will fail and may leave the device in a strange state. This call should work after the initial registration and a restart of the application.WARNING #2:
A successful call to deregistration will leave the current application session without required credentials and settings. You must restart the application to re-register the application and retrieve new credentials.This should be considered an advanced feature. If you make this available to end users, it should not be made too easily accessible and the UI control should be marked and possibly labeled to accentuate that it will wipe settings both in the cloud and locally on the device. We recommend that you also provide an additional user confirmation UI component to make it clear to the user what will occur and allow them to cancel the operation or proceed.
An asynchronous block callback parameter is provided for detecting the response.
callback
- The MASCallback that receives the results.public abstract boolean isRegistered()
public abstract void resetLocally()
Resets the application's locally stored data on the device only. This does NOT call the Gateway to remove the device record.
You must call deregister(MASCallback)
to do so.
public abstract java.lang.String getIdentifier()
public abstract void startAsBluetoothPeripheral(MASProximityLoginBLEPeripheralListener listener)
listener
- Register your listener to receive event and error during the session sharing.public abstract void stopAsBluetoothPeripheral()
public static MASDevice getCurrentDevice()
public void addAttribute(java.lang.String attr, java.lang.String value, MASCallback<java.lang.Void> callback)
attr
- Key of the attribute to be associated with the devicevalue
- Value of the attribute to be associated with the devicecallback
- MASCallback The callback to notify when a response is availablepublic void removeAllAttributes(MASCallback<java.lang.Void> callback)
callback
- MASCallback The callback to notify when a response is availablepublic void removeAttribute(java.lang.String attr, MASCallback<java.lang.Void> callback)
attr
- Key of the attribute to be removed for the current devicecallback
- MASCallback The callback to notify when a response is availablepublic void getAttribute(java.lang.String attr, MASCallback<org.json.JSONObject> callback)
attr
- Key of the attribute to be removed for the current devicecallback
- MASCallback The callback to notify when a response is availablepublic void getAttributes(MASCallback<org.json.JSONArray> callback)
callback
- MASCallback The callback to notify when a response is available


References
AVLTree/src/lib
| summary | ||
| public |
C AVLTree AVLTree with superpowers! 💪 |
BinaryTree/src/lib
| summary | ||
| public |
BinaryTree with superpowers! 💪 |
|
| public |
C TreeNode TreeNode |
|
| public |
V TraversalType: {"PRE_ORDER": string, "IN_ORDER": string, "POST_ORDER": string, "LEVEL_ORDER": string} |
BubbleSort/src/lib
| summary | ||
| public |
F bubbleSort(arr: *, comparator: *): * |
InsertionSort/src/lib
| summary | ||
| public |
F insertionSort(arr: *, comparator: *): * |
LinkedList/src/lib
| summary | ||
| public |
LinkedList with superpowers! 💪 |
|
| public |
C ListNode ListNode |
Math/src/lib
| summary | ||
| public |
F factorial(num: number): number Factorial |
|
| public |
F gcd(numA: number, numB: number): number Greatest common divisor |
|
| public |
F lcm(numA: number, numB: number): number Least common multiple |
|
| public |
F randrange(start: number, stop: number): number Random number |
|
| public |
V _Math: * Math with superpowers! 💪 |
MergeSort/src/lib
Number/src/lib
| summary | ||
| public |
C _Number Number with superpowers! 💪 |
|
| public |
|
|
| public |
|
PriorityQueue/src/lib
| summary | ||
| public |
PriorityQueue with superpowers! 💪 |
|
| public |
QueueNode |
Queue/src/lib
| summary | ||
| public |
C Queue Queue with superpowers! 💪 |
QuickSort/src/lib
| summary | ||
| public |
F partitionHoare(arr: Array<number>, low: number, high: number, pivotType: string, compare: Comparator): number Partition (Hoare) it is more efficient than the Lomuto partition scheme because it does three times fewer swaps on average |
|
| public |
F partitionLomuto(arr: Array<number>, low: number, high: number, pivotType: PivotType, compare: Comparator): number Partition (Lomuto) |
|
| public |
F quickSort(arr: Array<Item>, comparator: Comparator): Array<Item> QuickSort with superpowers! 💪 |
|
| public |
V PartitionType: {"LOMUTO": string, "HOARE": string} |
|
| public |
V PivotType: {"LOW": string, "HIGH": string, "MID": string, "RANDOM": string} |
SelectionSort/src/lib
| summary | ||
| public |
F selectionSort(arr: *, comparator: *): * |
Set/src/lib
| summary | ||
| public |
T Callback: Function |
String/src/lib
| summary | ||
| public |
C _String String with superpowers! 💪 |
Trie/src/lib
| summary | ||
| public |
C Trie Trie with superpowers! 💪 |
|
| public |
C TrieNode |
|
| public |
V SpecialChar: {"ROOT": string} |


A C++ library for Bayesian modeling, with an emphasis on Markov chain Monte Carlo. Although boom contains a few R utilities (mainly plotting functions), its primary purpose is to install the BOOM C++ library on your system so that other packages can link against it.
| Version: | 0.8 |
| Depends: | MASS, R (≥ 3.1.0) |
| LinkingTo: | BH (≥ 1.65.0), RcppEigen (≥ <IP_ADDRESS>.0) |
| Published: | 2018-04-29 |
| Author: | Steven L. Scott is the sole author and creator of the BOOM project. Some code in the BOOM libraries has been modified from other open source projects. These include Cephes (obtained from Netlib, written by Stephen L. Moshier), NEWUOA (M.J.D Powell, obtained from Powell's web site), and a modified version of the R math libraries (R core development team). Original copyright notices have been maintained in all source files. In these cases, copyright claimed by Steven L. Scott is limited to modifications made to the original code. Google claims copyright for code written while Steven L. Scott was employed at Google from 2008 - 2018, but BOOM is not an officially supported Google project. |
| Maintainer: | Steven L. Scott <steve.the.bayesian at gmail.com> |
| License: | LGPL-2.1 | file LICENSE |
| NeedsCompilation: | yes |
| SystemRequirements: | GNU Make, C++11 |
| In views: | Bayesian |
| CRAN checks: | Boom results |
| Reference manual: | Boom.pdf |
| Package source: | Boom_0.8.tar.gz |
| Windows binaries: | r-devel: Boom_0.8.zip, r-release: Boom_0.8.zip, r-oldrel: Boom_0.8.zip |
| OS X binaries: | r-release: Boom_0.8.tgz, r-oldrel: Boom_0.8.tgz |
| Old sources: | Boom archive |
| Reverse depends: | BoomSpikeSlab, bsts |
| Reverse imports: | CausalImpact, cbar |
| Reverse linking to: | bsts |
Please use the canonical form https://CRAN.R-project.org/package=Boom to link to this page.


List product description
Your tiny, dual-display, desktop computer…and robot brains, smart home hub,edia centre, networked AI core
Your tiny, dual-display, desktop computer…and robot brains, smart home hub,edia centre, networked AI core.
The Raspberry Pi 2 Model B is the second-generation Raspberry Pi.
Raspberry Pi Camera Module V2 có một cảm biến 8-megapixel của Sony IMX219 .


--- layout: post title: Top Ten AppleScript Tips categories: [] tags: [] status: publish type: post published: true meta: _original_post_id: '' _original_import_author: John Duprey author: ---
jduprey
curious


Konsulta
Social Funding
Barangay 41 at Mandaue City
Families:
31
Population:
189
Average Cases Per Month:
56
Disease Risks:
Dengue, Polio
Sponsors:
22
Average Sponsor Cost Per Month:
P217.50
Sponsorship Queue
John Smith (P267.00 of P1,000.00 this month)
Jane Doe (P129.00 of P500.00 this month)
Maria Clara (P195.00 of P1,200.00 this month)
Crisostomo Ibarra (P729.00 of P5,000.00 this month)
Jose Rizal (P329.00 of P1,500.00 this month)
« ‹ › »
Sponsorship Cases
Case ID
Case Date
Patient Name
Diagnosis
Status
Result
Total Cost
Sponsor
ID-76CEA9
05/10/2019 17:32:57
Juan Flavier
Fever
Closed
Medicine Prescription
P54.50
John Doe
Edit My Sponsorship
Exit This Sponsorship


THE ENGLISH PATIENT A film review by Scott Renshaw Copyright 1996 Scott Renshaw
(Miramax) Starring: Ralph Fiennes, Juliette Binoche, William Dafoe, Kristin Scott Thomas, Naveen Andrews, Colin Firth. Screenplay: Anthony Minghella. Producer: Saul Zaentz. Director: Anthony Minghella.  Reviewed by Scott Renshaw.
Michael Ondaatje's Booker Prize-winning novel _The English Patient_ looked to be a remarkably difficult work to translate to the screen. A tale of intertwined lives which weaves its way through several time periods with a lyrical, dream-like prose style, it is the kind of narrative which could turn into a catastrophic failure as much in the hands of a too-reverential film-maker as a completely oblivious one. So Anthony Minghella decided to build his own narrative around what he saw as the crux of _The English Patient_, and in so doing he has created a magnificent love story which gives "old-fashioned" a good name. Though miles removed from Ondaatje's psychological drama, Minghella's THE ENGLISH PATIENT stands on its own as a powerful sweeping romance..
THE ENGLISH PATIENT opens near the end of World War II, with a Canadian nurse named Hana (Juliette Binoche) who has grown weary of losing friends and lovers. When her medical unit is moving through Italy, Hana decides to stay behind in an abandoned monastery with one patient, a badly burned man who can't remember his name and is known only as "the English patient (Ralph Fiennes). His identity is of interest, however, to David Caravaggio (Willem Dafoe), a maimed former Allied agent who believes the English patient was the Axis spy who gave him up. Meanwhile, in flashback we see the patient's memories of himself as the Hungarian count Laszlo de Almasy, a cartographer exploring the North African desert who meets Katherine Clifton (Kristin Scott Thomas), the wife of one of his colleagues. The two begin an affair which brings Almasy to life, but is destined to leave him in that makeshift Italian hospital bed.
Anthony Minghella's resume has thus far consisted of supernatural romance (TRULY, MADLY, DEEPLY) and blue collar romance (MR. WONDERFUL), but THE ENGLISH PATIENT is a romance with the kind of sweep you associate with films made, and not merely set, in the 1940s. Ralph Fiennes turns in a wonderfully economical performance as Almasy, a reserved man who begins with the minimalist philosophy that "a thing is a thing" but becomes utterly intoxicated by the first real passion in his life. Fiennes is exceptional behind layers of prosthetics (created by Jim Henson's Creature Shop), and makes Almasy's later witty resignation entirely consistent with the man he becomes in the scenes set years earlier. Kristin Scott Thomas matches his work with a radiant sensuality, turning the smart, perceptive Katherine a deserving object of any man's fixation. Thomas and Fiennes share the kind of beautiful but intense chemistry movies seem reluctant to show us in 1996, perhaps afraid that a cynical modern audience will not be able to take such deeply felt emotions seriously. It is not every writer who would risk dialogue like "Every night I cut out my heart, but in the morning it was full again;" it is not every director who would stage the defining moment in a relationship -- a scene in which Almasy and Katherine share a dance to, appropriately enough, "Where or When" -- with virtually no dialogue, the attraction conveyed through a soul-piercing gaze by Fiennes.
Those familiar with the novel may have noticed the conspicuous absence of Kip Singh, a Sikh bomb defuser who shares an odd affair with Hana. Both the character (portrayed by Naveen Andrews) and the relationship appear in THE ENGLISH PATIENT, but their role is greatly reduced in Minghella's account, as is that of Caravaggio. Minghella tries to link the two love stories in his film, but that may be the one place he is less than successful -- he has focused his story so decidedly on Almasy and Katherine that the peripheral characters are sometimes more distracting than complementary. It is to Minghella's credit, however, that he has clarified a number of points in his streamlined narrative, creating a uniquely powerful story, less intricate and internalized than Ondaatje's novel but just as involving.
The quality which may make THE ENGLISH PATIENT so singularly effective is its refusal to fit into neatly-defined categories of romantic film-making.  As risky as it might be to throw around comparisons with classics, THE ENGLISH PATIENT is the kind of combination of humor, detailed characterization, passion and politics which recalls CASABLANCA. Almasy and Katherine may share an on-screen consummation which cinema could not attempt 50 years ago, but in most other ways the central love story of THE ENGLISH PATIENT warrants consideration among the great tragic pairings. Minghella's risky adaptation has paid off gloriously, proving they _can_ make 'em like they used to.
On the Renshaw scale of 0 to 10 patient virtues: 9.
Visit Scott Renshaw's MoviePage http://www-leland.stanford.edu/~srenshaw Subscribe to receive reviews directly via email See details on the MoviePage
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


Password Generator
Password Length
Include Uppercase
Include Lowercase
Include Number
Include Symbol
Generate Password


Hovering over each thumbnail in the image carousel will launch a tooltip window displaying the details of the thumb.
Please visit Demo 5: Show thumbnail details with Tooltip widget for detailed instructions, or visit the Full documentation of the image slider.


Your RMA request has been received. Once it's been reviewed and processed, you'll receive an update with next steps. Thank you.


"TROPHIMUS "a foster-child, an Ephesian who accompanied Paul during a part of his third missionary journey (Acts 20:4; 21:29). He was with Paul in Jerusalem, and the Jews, supposing that the apostle had brought him with him into the temple, raised a tumult which resulted in Paul’s imprisonment. (See TEMPLE, HEROD’S.) In writing to Timothy, the apostle says, “Trophimus have I left at Miletum sick” (2 Timothy 4:20). This must refer to some event not noticed in the Acts.
"TROPHIMUS "a foster-child, an Ephesian who accompanied Paul during a part of his third missionary journey (Acts 20:4; 21:29). He was with Paul in Jerusalem, and the Jews, supposing that the apostle had brought him with him into the temple, raised a tumult which resulted in Paul’s imprisonment. (See TEMPLE, HEROD’S.) In writing to Timothy, the apostle says, “Trophimus have I left at Miletum sick” (2 Timothy 4:20).
This must refer to some event not noticed in the Acts.


University life is more interesting when you are part of a community
The Campus is an enterprise social network designed to integrate purposeful social collaboration into learning. It serves as a virtual Campus for students within an academic institution.
If you can’t find the answer to your question, please contact us.


#include <array_ops.h>
Unpacks a given dimension of a rank-R
tensor into num
rank-(R-1)
tensors.
Unpacks num
tensors from value
by chipping it along the axis
dimension. For example, given a tensor of shape (A, B, C, D)
;
If axis == 0
then the i'th tensor in output
is the slice value[i, :, :, :]
and each tensor in output
will have shape (B, C, D)
. (Note that the dimension unpacked along is gone, unlike split
).
If axis == 1
then the i'th tensor in output
is the slice value[:, i, :, :]
and each tensor in output
will have shape (A, C, D)
. Etc.
This is the opposite of pack
.
Arguments:
axis
dimension size equal to num
.Optional attributes (see Attrs
):
[-R, R)
.Returns:
OutputList
: The list of tensors unpacked from value
.
Constructors and Destructors |
|
|---|---|
Unstack(const ::tensorflow::Scope & scope, ::tensorflow::Input value, int64 num)
|
|
Unstack(const ::tensorflow::Scope & scope, ::tensorflow::Input value, int64 num, const Unstack::Attrs & attrs)
|
Public attributes |
|
|---|---|
operation
|
|
output
|
Public functions |
|
|---|---|
operator[](size_t index) const
|
Public static functions |
|
|---|---|
Axis(int64 x)
|
Structs |
|
|---|---|
|
tensorflow:: |
Optional attribute setters for Unstack. |
Operation operation
::tensorflow::OutputList output
Unstack( const ::tensorflow::Scope & scope, ::tensorflow::Input value, int64 num )
Unstack( const ::tensorflow::Scope & scope, ::tensorflow::Input value, int64 num, const Unstack::Attrs & attrs )
::tensorflow::Output operator[]( size_t index ) const
Attrs Axis( int64 x )


{{ partial "common/head.html" . }} {{ partial "common/nav.html" . }} {{ partial "common/header.html" . }} {{ .Content }} Copyright © Peter Y. Chuang {{ .Site.LastChange.Year }} {{ partial "common/author.html" . }} {{ partial "common/footer.html" . }}
Copyright © Peter Y. Chuang {{ .Site.LastChange.Year }}


|
Ubiquity
2.3.0
php rapid development framework
|
Http Response utilities Ubiquity$UResponse This class is part of Ubiquity. More...
Static Public Member Functions | |
| static | header ($headerField, $value, bool $replace=true, int $responseCode=null) |
| Send a raw HTTP header. More... | |
| static | setContentType ($contentType, $encoding=null) |
| Sets header content-type. More... | |
| static | noCache () |
| Forces the disabling of the browser cache. More... | |
| static | isSent (&$file=null, &$line=null) |
| Checks if or where headers have been sent. More... | |
| static | asJSON () |
| Sets the response content-type to application/json. More... | |
| static | isJSON () |
| Tests if response content-type is application/json Only Works if UResponse has been used for setting headers. More... | |
| static | asHtml ($encoding='utf-8') |
| Sets the response content-type to text/html. More... | |
| static | asXml ($encoding='utf-8') |
| Sets the response content-type to application/xml. More... | |
| static | asText ($encoding='utf-8') |
| Sets the response content-type to plain/text. More... | |
| static | setAccept ($value) |
| Sets the Accept header. More... | |
| static | enableCors ($origin=' *', $methods='GET, POST, PUT, DELETE, PATCH, OPTIONS', $headers='X-Requested-With, Content-Type, Accept, Origin, Authorization') |
| Enables CORS. More... | |
| static | setAccessControlOrigin ($origin=' *') |
| Sets the Access-Control-Allow-Origin field value Only a single origin can be specified. More... | |
| static | setAccessControlMethods ($methods) |
| Sets the Access-Control-Allow-Methods field value. More... | |
| static | setAccessControlHeaders ($headers) |
| Sets the Access-Control-Allow-Headers field value. More... | |
| static | setAuthorization ($authorization) |
| Set the Authorization header field. More... | |
| static | setResponseCode ($value) |
| Sets the response code. More... | |
| static | getResponseCode () |
| Get the response code. More... | |
Static Public Attributes | |
| static | $headers = [ ] |
Static Private Member Functions | |
| static | _headerArray ($headerField, $values) |
Http Response utilities Ubiquity$UResponse This class is part of Ubiquity.
Definition at line 16 of file UResponse.php.
|
staticprivate |
| string | $headerField | |
| mixed | $values |
Definition at line 37 of file UResponse.php.
|
static |
Sets the response content-type to text/html.
| string | $encoding | default: utf-8 |
Definition at line 98 of file UResponse.php.
|
static |
Sets the response content-type to application/json.
Definition at line 79 of file UResponse.php.
|
static |
Sets the response content-type to plain/text.
| string | $encoding | default: utf-8 |
Definition at line 116 of file UResponse.php.
|
static |
Sets the response content-type to application/xml.
| string | $encoding | default: utf-8 |
Definition at line 107 of file UResponse.php.
|
static |
Enables CORS.
| string | $origin | The allowed origin (default: '*') |
| string | $methods | The allowed methods (default: 'GET, POST, PUT, DELETE, PATCH, OPTIONS') |
| string | $headers | The allowed headers (default: 'X-Requested-With, Content-Type, Accept, Origin, Authorization') |
Definition at line 138 of file UResponse.php.
|
static |
|
static |
Send a raw HTTP header.
| string | $headerField | the header field |
| string | $value | the header value |
| boolean | $replace | The optional replace parameter indicates whether the header should replace a previous similar header |
| int | $responseCode | Forces the HTTP response code to the specified value |
Definition at line 27 of file UResponse.php.
|
static |
Tests if response content-type is application/json Only Works if UResponse has been used for setting headers.
Definition at line 89 of file UResponse.php.
|
static |
Checks if or where headers have been sent.
| string | $file | If the optional file and line parameters are set,headers_sent will put the PHP source file nameand line number where output started in the fileand line variables. |
| int | $line | The line number where the output started. |
Definition at line 72 of file UResponse.php.
|
static |
Forces the disabling of the browser cache.
Definition at line 60 of file UResponse.php.
|
static |
Sets the Accept header.
| string | $value | one of Http accept values |
Definition at line 126 of file UResponse.php.
|
static |
Sets the Access-Control-Allow-Headers field value.
| string | array | $headers |
Definition at line 171 of file UResponse.php.
|
static |
Sets the Access-Control-Allow-Methods field value.
| string | array | $methods |
Definition at line 162 of file UResponse.php.
|
static |
Sets the Access-Control-Allow-Origin field value Only a single origin can be specified.
| string | $origin |
Definition at line 150 of file UResponse.php.
|
static |
Set the Authorization header field.
| string | $authorization |
Definition at line 180 of file UResponse.php.
|
static |
Sets header content-type.
| string | $contentType | |
| string | $encoding |
Definition at line 50 of file UResponse.php.
|
static |
|
static |
Definition at line 17 of file UResponse.php.


Operational
Insight
Hi <%= firstName %>,
It's time to update your workload on Operational Insight! Please remember to log in to Operational Insight to validate your current projects.


eeprivacy¶
Operations¶
An Operation encapsulates the full workflow of common analytics tasks: running statistics (like means, histograms, and quantiles), reporting on accuracy, and supporting analysis of privacy/accuracy tradeoffs.
-
class
eeprivacy.operations.
PrivateAboveThreshold
¶ Return the index of the first query that exceeds a target threshold.
This technique was first describe in Chapter 3.6 of [Dwork and Roth] and the implementation below is based on Chapter 10 of Programming Differential Privacy [Near].
References
Dwork, C., Roth, A., 2013. The Algorithmic Foundations of Differential Privacy. FNT in Theoretical Computer Science 9, 211–407. https://doi.org/10.1561/0400000042
Near, J. 2020. Programming Differential Privacy. https://uvm-plaid.github.io/programming-dp/notebooks/ch10.html
-
execute
(*, queries: List[float], threshold: float, epsilon: float)¶ - Parameters
queries – List of sensitivity-1 queries to choose from
threshold – Threshold above which the first query will be returned
epsilon – Privacy parameter
- Returns
The index of the query that exceeds threshold.
-
class
eeprivacy.operations.
PrivateClampedMean
(*, lower_bound: float, upper_bound: float)¶ Compute a mean, bounding sensitivity with clamping. Employs the Laplace Mechanism.
-
confidence_interval
(*, epsilon, N, confidence=0.95)¶ Compute the two-sided confidence interval for the mean.
-
epsilon_for_confidence_interval
(*, target_ci, N, confidence=0.95)¶ Return epsilon for a desired confidence interval.
-
execute
(*, values: List[float], epsilon: float) → float¶ Computes the mean of values privately using a clamped mean.
Implements Algorithm 2.3 from [Li et al]
- Returns
The private mean.
References
Li, N., Yang, W., Lyu, M., Su, D. (2016). Differential Privacy: From Theory to Practice. United States: Morgan & Claypool Publishers.
-
-
class
eeprivacy.operations.
PrivateClampedSum
(*, lower_bound: float, upper_bound: float)¶ Compute a sum, bounding sensitivity with clamping. Employs the Laplace Mechanism.
-
confidence_interval
(*, epsilon, confidence=0.95)¶ Compute the two-sided confidence interval for the sum.
-
epsilon_for_confidence_interval
(*, target_ci, confidence=0.95)¶ Return epsilon for a desired confidence interval.
-
execute
(*, values: List[float], epsilon: float) → float¶ Computes the mean of values privately using a clamped sum.
- Returns
The private sum.
-
-
class
eeprivacy.operations.
PrivateHistogram
(*, bins: List[float], max_individual_contribution: int = 1)¶ Compute a private histogram with the Laplace Mechanism.
- Parameters
bins – Edges of bins for results. These must be specified up-front otherwise information will be leaked by the choice of bins. Read more
max_individual_contribution – Maximum count any individual in the dataset could contribute to the histogram. Normally 1.
-
confidence_interval
(*, epsilon: float, confidence: float = 0.95) → float¶ Return the confidence interval for each bar of the histogram.
-
execute
(*, values: List[float], epsilon: float) → List[float]¶ Computes the histogram of values privately.
Values are clamped to the bound specified by
bins
.- Returns
A list of private counts, one for each bin.
-
class
eeprivacy.operations.
PrivateQuantile
(*, options: List[float], max_individual_contribution: int = 1)¶ Find quantiles privately with the Report Noisy Max mechanism.
- Parameters
options – List of possible outputs
max_individual_contribution – Normally 1, unless an individual can contribute multiple points to the dataset.
-
execute
(*, values: List[float], epsilon: float, quantile: float)¶ Computes the quantile of a list of values privately.
Implemented using Report Noisy Max (Claim 3.9) of [Dwork and Roth].
- Parameters
values – Dataset
epsilon – Privacy parameter
quantile – Quantile to return (between 0 and 1)
References
Dwork, C., Roth, A., 2013. The Algorithmic Foundations of Differential Privacy. FNT in Theoretical Computer Science 9, 211–407. https://doi.org/10.1561/0400000042
-
class
eeprivacy.operations.
PrivateVectorClampedMeanGaussian
(*, lower_bound: float, upper_bound: float, k: float, N: float)¶ A vector mean computes the elementwise mean of a vector-valued dataset. That is, a dataset in which each row is a vector of values corresponding to each individual. For example:
six_hourly_energy_consumptions = [ [4.2, 11.1, 14.1, 3.2], [1.4, 4.5.1, 4.8, 1.6], ... ]
This implementation requires the size of the dataset upfront (either pass it exactly if it is not private or compute with a private count).
With the Gaussian Mechanism, noise is scaled to the L2 norm of the dataset.
- Parameters
lower_bound – Lower bound of input data
upper_bound – Upper bound of input data
k – Size of vectors in dataset
N – Number of elements in dataset
-
confidence_interval
(*, epsilon: float, delta: float, confidence: float = 0.95) → float¶ Compute the two-sided confidence interval for the mean.
-
epsilon_for_confidence_interval
(*, target_ci: float, delta: float, confidence: float = 0.95) → float¶ Return epsilon for a desired confidence interval.
-
execute
(*, vectors: List[float], epsilon: float, delta: float) → float¶ Computes the elementwise mean of vectors privately using a clamped sum and exact count with the Gaussian Mechanism.
-
class
eeprivacy.operations.
PrivateVectorClampedMeanLaplace
(*, lower_bound: float, upper_bound: float, k: float, N: float)¶ A simple implementation of the mean operation that requires the size of the dataset up front (either pass it exactly if it is not private or compute with a private count).
With the Laplace Mechanism, noise is scaled to the L1 norm of the dataset.
- Parameters
lower_bound – Lower bound of input data
upper_bound – Upper bound of input data
k – Size of vectors in dataset
N – Number of elements in dataset
-
execute
(*, vectors: List[float], epsilon: float, delta: float) → float¶ Computes the mean of vectors privately using a clamped sum and exact count with the Laplace Mechanism.
Mechanisms¶
Mechanisms are differential privacy primitives. The raw implementations should be used with care by non-experts.
A Note on Confidence Intervals¶
The confidence intervals returned by Mechanism classes are two-sided.
For example, in the algorithm design helper function epsilon_for_confidence_interval the ε value returned for the Laplace Mechanism at the default confidence = 0.95 and target_ci = 5, the distribution of outputs for the returned ε would be the following:
2.5% │ █ │ 2.5%
◀──────│ █ │──────▶
│ █ │
│ ███ │
│ ███ │
│ ███ │
│ ███ │
│ ███ │
│ █████ │
│ ███████ │
│ █████████ │
│█████████████│
███│█████████████│███
─────┼──────┬──────┼────
│ │ │
True
-5 Count 5
-
class
eeprivacy.mechanisms.
GaussianMechanism
¶ The Gaussian Mechanism.
-
static
confidence_interval
(*, epsilon: float, delta: float, sensitivity: float, confidence: float = 0.95) → float¶ Return the confidence interval for the Gaussian Mechanism at a given epsilon, delta, and sensitivity.
-
static
epsilon_for_confidence_interval
(target_ci: float, sensitivity: float, delta: float, confidence: float = 0.95) → float¶ Returns the ε for the Gaussian Mechanism that will produce outputs +/-target_ci at confidence for queries with sensitivity and delta.
-
static
execute
(*, value: float, epsilon: float, delta: float, sensitivity: float) → float¶ Run the Gaussian Mechanism, adding noise to value to realize differential private at (epsilon, delta) for the provided sensitivity.
-
static
execute_batch
(*, values: List[float], epsilon: float, delta: float, sensitivity: float) → List[float]¶ Run the Gaussian Mechanism, adding noise to value to realize differential private at (epsilon, delta) for the provided sensitivity.
Runs the Gaussian Mechanism multiple times, once for each item in the list.
-
static
-
class
eeprivacy.mechanisms.
LaplaceMechanism
¶ The Laplace Mechanism.
-
static
confidence_interval
(*, epsilon: float, sensitivity: float, confidence: float = 0.95) → float¶ Determine the two-sided confidence interval for a given privacy parameter.
-
static
epsilon_for_confidence_interval
(*, target_ci: float, sensitivity: float, confidence: float = 0.95) → float¶ Determine the privacy parameter for a desired accuracy.
-
static
execute
(*, value: float, epsilon: float, sensitivity: float) → float¶ Run the Laplace Mechanism, adding noise to value to realize differential private at epsilon for the provided sensitivity.
-
static
execute_batch
(*, values: List[float], epsilon: float, sensitivity: float) → List[float]¶ Run the Laplace Mechanism, adding noise to value to realize differential private at epsilon for the provided sensitivity.
Runs the Laplace Mechanism multiple times, once for each item in the list.
-
static


World Creation
Here you have to ask yourself a number of broad questions, each of them is meant to give a better idea of what will be in the
world, what won’t, and how to build it.
1. How old is my world?: Remember that the world must be old enough for the story to take place. Planets are not formed
in days, they are formed over eons of time. Billions of years for the process of rock formation and volcanic activity to
give way to basic life forms which evolve in complexity over many millions upon millions of years until humanoids
evolve. Then of course, humanoid civilization takes many thousands, if not millions of years to evolve in complexity,
as many start out as tribal hunter-gatherers, slowly settling down into sedentary lifestyles, and developing culture,
language, and technology. To give you an idea, as of the year 2015, the Earth is roughly 4.5 Billion years old, and
modern humans have only existed for about 200,000-1 million years, which is relatively short.
2. How developed is my world?: This gets more into the people and civilizations of your world. By nature of playing
The Arcane Engine, it necessitates a number of assumptions about the technological level of your world, but that
doesn’t mean that socio-cultural development has kept pace, nor does it mean that all this technology affords
humanoids dominance over the natural world. How much of the planet’s surface could be considered, “civilized”? Is
the whole world within the reach of one or another sprawling empire, or is the world still wild, with pockets of capable
civilizations?
3. How wild is my world?: If you choose to have a wild world where humanoids cannot dominate the landscape, what is
stopping them? Surely with massive machines, guns, explosives, magic, etc. Humanoids could rule the landscape? This
question can have many answers, such as a dearth of resources, of course no one can build that many machines if iron
deposits are rare.  Perhaps the landscape is so filled with war, and the kingdoms of humanoids are
so distrusting of each other that populations never reach levels high enough to tame the landscape.
4. How rich is my world?: This question flows naturally out of the last one, and doesn’t refer to money, as money is
an invention. How much of any and all natural resources are on your world? If gold is everywhere it won’t become a
commodity, because everyone has it. If Iron is extremely rare, then war is harder to wage as weapons are harder to make,
and iron mines are national treasures. In addition, in such a world, any scrap metal left over from destroyed machines
would be scrounged up immediately and sold quickly. A world mired in war must have a rich stock of resources to fuel
those wars.
5. How old is civilization?: When did humanoids start to develop complex cultural civilizations? An easy marker to begin
with is the widespread development of agriculture. Sedentary lifestyle was based around the demands of farming, and
farming was adopted as a way to easily and efficiently make food. Deliberate cultivation and animal domestication
began on earth somewhere between 10,000-13,000 years ago. Though it is common to include some cataclysmic event
that reset civilization and extends the development time of humanoid civilization to the current date within your game.
6. Where did civilization begin? How did it spread?: Generally, the first signs of agricultural development will be in
very fertile areas where crops are easy to grow. On Earth, farming began in the Fertile Crescent, an area that enveloped
the ancient lands of Mesopotamia, Phoenicia, and Egypt. These areas are today Egypt, Israel, Iraq, Iran, and their
surrounding nations. This is important because where civilization began, characters will find the oldest ruins, and
possibly some of the strangest remains…perhaps ancient magic? In addition, this allows for the development of larger
and more established civilizations, as technology and culture will flow from already established cultures to new lands
where they will be adopted by less advanced people.
7. Where are resources most plentiful?: Simply put, the land with the most resources will end up becoming the most
powerful nation. Though often, certain lands are rich in certain resources, while others are rich in different resources. If
gold is rare, then a country with massive gold deposits will be rich, and are in a good position to become trade masters.
The country with the most fertile land will have a higher population, and of course that means larger cities, and larger
armies. The land with the most iron will have more iron items, and will be able to field better equipped armies, as they
have the materials for good armor and weapons without having to import them.
8. How many states exist in this world? Are they peaceful or not?: This is simple, if you want to have a lot of kingdoms
in your world, they will be smaller and there will probably be more war. On the other hand, larger kingdoms, and
empires, will often also have war, but the scale will be much larger and more widespread.
9. How much magic exists in this world?: Magic is a part of this system, a very integral part. So how much magic exists
in the world? Is technology much more common, or is there magic to go around constantly? Does everyone have access
to it, or is it expensive and hereditary? Magic will also shape culture, and often has an effect on the distribution and
development of kingdoms. Be mindful of all this.
Adventures, or campaigns, are strings of scenarios and encounters put together by an overarching story, which includes a consistent cast of characters. Adventures are incredibly rewarding and interesting, because it allows players to see characters develop over a longer period of time, and see a story through a satisfying end. GM’s should communicate what type of campaign they would like to play to their players. If the campaign is to be structured, then the GM should make their campaign after the players make their characters, so as to build the campaign in a way that incorporates each players’ character seamlessly. For Game Masters, designing an adventure can take a long time, and it is good to get collaboration from your players in what campaign to run.
A Problem That Needs Solving:
There must be something to overcome, a specific reason why the party would go forth and do what they are doing. This
can be as simple as a singular assassination contract, or a multiple part, world-wide treasure hunt. The problem may
simply be that the party wants an item and will do whatever is needed to obtain that item. The problem must however be
worthy of their attention and valuable to them in some way, even if it’s only valuable to give to someone else.
A Clear Goal:
Characters must have a clear goal to work towards. In a structured campaign, this is very easy to set up, and the goal
is ever-present. In a free form campaign, this means that the characters must always have something to do. It is not
necessarily something they should or will do, but merely something that they can do.
Meaningful Outcomes for
Everyone:
This means two things: That the players should have choices that actually matter to the outcome of the story, and that
there should be choices that everyone can participate in.
Interesting Encounters:
Encounters, which are covered later, are the basis of what a campaign is identified by. In essence, a campaign is a
series of encounters. Each of these encounters should be interesting and meaningful. Having filler fights for the sake
of fighting is not a good way to go about it. Players should feel like every encounter, whether social or martial, has a
meaning. Do not just randomly set enemies upon your players, with no outcomes for winning beyond experience and
loot. The enemies should have a purpose to be there. This is not to say that random encounters are not good, but just
that random encounters for the sake of randomness is not good. If the players are attempting to fight through a docks
district to catch a VIP, then random henchmen or bodyguards popping up to fight the players is meaningful. They are not
just there to fight the players, they are there to defend the VIP. Even if the enemies are there just to weaken the players
and expend valuable items before the players fight some monster at the end of a tunnel system is meaningful, even
though it may not appear so.
Going beyond the campaign itself to the building blocks that comprise the body of a campaign, encounters form the basis of interaction for your players. They do not interact with the campaign as a whole, instead, they interact with the individual encounters that make up the campaign. The types of encounters generally include storytelling encounters, combat encounters, investigative encounters, social encounters, explorative encounters, and skill encounters.
Clear Goal:
A GM must have a clear goal for an encounter. There should never be encounters where nothing is
accomplished. Of course, the GM should not attempt to force their ideal resolution to an encounter that would
be railroading. The point is to make the encounter meaningful. Combat not just for the sake of combat, but to
do something beyond, to symbolize a purpose or forward an agenda. A social encounter should never end with
an awkward silence and no progress; ending the social encounter having made a bitter enemy of the players is
still progress, and possible plot points later on.
Interesting Developments:
Simply put, an encounter should have some interesting developments made so that the players actually feel
invested in the outcome. Players should never feel like the encounter they ended was completely frivolous
and pointless. It is up the GM to specially craft encounter so as to make them interesting, and with interesting
outcomes. Encountering the barbarian tribe should make the players excited or nervous, because the
barbarians should pose a significant threat while the players finish another objective in the area. Talking
with the local lord should give the players a mission that is both interesting and challenging. For a group of
master level mages and weapon experts, a den of overgrown rats is hardly challenging or interesting. An evil
cult attempting to raise a demon is much more interesting, mostly because it actually poses a challenge to
the players’ abilities. Players like to see their characters constantly grow and overcome greater and greater
challenges, so give them such.
Fun for Everyone:
An encounter should be fun for everyone involved. Again, this goes back to the fact that the players should be
challenged, but the players should also actually be having fun. A slugfest against equally matched opponents
is challenging, but hardly fun. The players should be given opportunities to show their tactical prowess and
critical thinking skills, and rewarded with bonuses that affect their dice rolls. Social encounters should not just
be a simple roll vs another roll. There should be preparation and intrigue invested into the final conversation.
 NPC is a general term that refers to everyone else in the game world that is not actively controlled by one of the players at the game table. Every enemy, every shopkeeper, every civilian, and every critter that the players meet is an NPC, and is under the complete control of the GM. The players control their characters, and the GM quite literally plays as the rest of the world.
NPCs are not Player Characters:
The Player Characters are the center of the story. The players are your reason why this campaign is
happening, so you as the GM must understand that your part is to play the less important world around
them. Now this is not to say that anything that happens to anyone else isn’t as important within the game
world, but outside the game world, everyone else is, in fact, less important. NPCs should almost never
become the focus of your story, and if they must, they should not be able to drive the plot forward without
the aid of the player characters.
NPCs are People Too:
Just because NPCs are not as important as the players doesn’t mean they aren’t supposed to be living
thinking beings as well. They have emotions, they make mistakes, they are not all knowing, and they
don’t usually want to die. NPCs should react accordingly when the players do something. Even if the
NPC would severely complicate the lives of the Players, such as calling the police when the Players are
spotted committing a crime, that NPC should do so. It is what the NPC would do naturally.
The GM is not the NPC:
As a GM, you must understand above and beyond your players the necessity of separating in-game and
out-of-game knowledge. You as the GM understand what is going to happen in a few moments. You
know when the wolves are going to attack, and when the police are going to arrive. The NPC you are
playing as may not know these things. In combat, enemies are not perfectly coordinated unless they
have some sort of mental link. They often do not perform 4-part combos unless they happen to be some
special task-force that have worked together before.
Know the Rules:
GM’s are meant to be the rules keeper, and the arbiter of the game. The players will constantly ask you if anything
they are doing is ok to do, and if they can do something within the game. More importantly, they will ask you how to
do something, so having the rules ready both in your mind and in text are essential to being a good GM.
Know How to Break the Rules:
If the rules are too stringent for your tastes, or the rules are not correct in your mind or the mind of your players, you
must be a good improviser in making up other rules for the situation. This is especially important in places where there
is no specific rule. This book is not meant to be a replete composition of all possible scenarios and all possible rules.
In addition, if you make a new rule, you must be consistent with them. Players want to have a consistent set of rules so
they know what game they are playing.
 The players may object to some of your decisions, and they
may very well believe that your judgments are not right, but they, and you, must understand that the GM’s rulings are
final. Later on, you may come to find your old judgments are, in fact, wrong, and you can change them (Make sure to
apologize).
The Players are Not the Enemy:
If a Player does something you do not like, or if you feel that the players are doing too well and need challenging,
you must remember that the players are your friends, and collaborative storytellers. Often, GMs will see that they are
constantly playing the villain attempting to best the Player Characters, and will extrapolate that outside of the game
world. They will believe that the GM himself is supposed to best the Players at the table.  The Players come out on top, and
the GM just gets more frustrated, and schemes further. Take a step back, and realize that fighting your players leads
to bitterness, and a completely un-fun experience for everyone. Seeing the Players overcome a meaningful challenge
should provide you with the satisfaction you need. If you don’t derive satisfaction from helping other people succeed,
then being a GM may not be for you.
What Happens in Game, Stays in Game:
If a problem happens in game, it must stay within the game, and though players may be prone to bringing quarrels
outside of the game world, you as the GM should help them to cool off, and bring it back to reality. Romantic
relationships in the game do not mean anything outside of it, and arguments within the game should never cause the
players to actually get angry at each other.
In addition, things that happen outside the game should never make it into the game world.  If you dislike something someone did that day, their character should never suffer for
it.
Let Go of Your Creations:
Just because you created something does not mean that it means the same thing to the players. The immense effort
you put into building a storyline might be all for naught as the players kill the NPC that would introduce them to said
storyline. It is better for yourself and for everyone else if you calm down, and let go of things you hold dear.
Let the Players Help You:
Sometimes the work of creating the world can get overwhelming, this is completely understandable. It is always
recommended to let the players help in designing the world, especially if something they create is relatively
inconsequential outside of itself. Perhaps Player A has come from a small town not on the map. Alright, let him create
that town, and let him flesh it out. This adds to your world, it takes work away from you, and it gives your player
a wonderful sense of attachment to the world. In addition, remember that your players will feel attached to their
characters. These characters are the players’ insertion into the world, their creative sandbox. So let them do whatever
they want with their characters, within reason of course. A consequence of this is, be very careful taking control away from the players. This includes all types of mind control or action control. If your players no longer have their
characters, they have nothing…and if they have nothing, they have no reason to be at the table.
Have Fun with It:
This is a game, so have some fun! Your role as a GM was never mandated by anyone, and you are probably not being
paid to be a GM. It can feel like a job at times, and the players may never know the work you put into the game, but
that isn’t important. What is important is that you and your players have fun with the game. So enjoy yourself, and
enjoy the amazing collaborative experience that Tabletop RPGs can bring.


Psalms 35:7
For without cause have they hid for me their net in a pit, which without cause they have digged for my soul.