Git 1.6.6 and Xcode 3.2.x

July 12th, 2010

I like to use git as my primary source code version control. Git commands are simple to use and git’s method of branching, commits, tags are easy to understand and use. However, Xcode supports only svn within the IDE. Git can still be used with Xcode but a .gitignore file and .gitattributes file should be created.

The .gitignore File

In Xcode 3.2.x the *.xcodeproj folder contains project files specific to Xcode. I usually specify to git that the xcodeproj folder should be ignored, except for the pbxproj file within the folder.

#
# .gitignore file
#
# Ignore any build files and older project files
build/*
*.mode1v3
*.mode2v3
*.pbxuser
*.perspective 
*.perspectivev3

# Ignore the xcodeproj
*.xcodeproj

# Don't ignore the pbxproj within the xcodeproj folder
!*.xcodeproj/project.pbxproj

# Ignore .svn information
.svn

# Ignore OSX-specific files
.DS_Store
profile

The .gitattributes File

I usually specify to git that it should not convert, diff, or merge the *.pbxproj file.

#
#
# .gitattributes file
#
# Effectively treat the pbxproj as binary
#
*.pbxproj -crlf -diff -merge

Links

For more info about gitignore

For more info about gitattributes

When working with other developers, I like to chat on the server itself using talkd. Talkd is the server that notifies a user that someone else wants to initiate a conversation. It acts a repository of invitations, responding to requests by clients wishing to rendezvous to hold a conversation

apt-get install inetutils-inetd
apt-get install talk
apt-get install talkd
vi /etc/inetd.conf

Make sure you have in the /etc/inetd.conf the following:

talk dgram udp4 wait root /usr/sbin/in.talkd in.talkd
ntalk dgram udp4 wait root /usr/sbin/in.ntalkd in.ntalkd

/etc/init.d/inetutils-inetd restart

Three steps

1) The US government authorizes the release of gold from Fort Knox, via National Security or Executive Order

2) Chop it up into fine powder and mix the powdered gold with biodegradable material, so that it floats and will stick to the oil.

3) Seed the oil slicks with about 1 ounce per cubic foot of oil, on average.

RESULT: You’ll have lots of companies out there sucking the oil up, getting the gold and reselling the oil. you’ll have a gold rush on the beaches. You’ll have people out there getting the oil off the beach (to get the gold).

You’ll generate a short term micro-economy in the Gulf area, as support services are needed to support the gold rushers (hotels, restaurants, food, and equipment!).

Why not? The gold in Fort Knox does nothing, as is. It just sits there. About 4600 tons of gold is available. http://en.wikipedia.org/wiki/United_States_Bullion_Depository

The Digital Magazine previews, especially VIV Magazine, at http://vimeo.com/10204353 are extremely impressive.

From what I can see, Digital Magazines have both the interactivity of a website with high quality video that enhances the text, graphical content in a way that the normal web-browser is not currently capable.

This brings up some interesting questions:

- Are Digital Magazines the new Web 3.0; where the Digital Magazine on a iPad or tablet becomes a truly immersive experience, compared to a standard web-site. ?

- How will web design and web designers adapt to Digital Magazines on the iPad?

- Should these Digital Magazines be ignored? Are they a fad?

- Will Digital Magazines be the new “web” for the iPad or tablets?

According to City of Orlando’s Creative Village booklet, “Orlando is one of the top 12 digital media clusters in the country. A recent study by the research firm Catalytix validates that Orlando is poised to become a top destination for creative types. According to the study, there are 317 local film and entertainment technology businesses in the area that employ more than 8,000 workers, host $1.4 billion in annual sales and pay $280 million in salaries. Another 822 “arts” businesses employ 6,000 people.The average wage for Orlando’s high- tech worker is $70,000.” (Film & Entertainment Technology: Opportunities and Obstacles for Sustainable Regional Growth, Catalytix; Study Commissioned by The Metro Orlando Economic Development Commission; delivered October 11, 2006.)

It seem from the above Study that Orlando has the creative people, we have the local film and entertainment technology businesses.

Can Orlando become the premiere production-center for Digital Magazines, here in Florida?

If not, why not?!

Is Orlando doomed to wait for Los Angeles and New York to take the lead? ;

Time Capsule + iPad

March 18th, 2010

If Apple were to update the Time Capsule to become an external database storage hub for the iPad, it would create a huge ecosystem. This new ecosystem would be based upon the Time Capsule having an API that would be accessible from the iPad OS.

Such an combination of products, would open iPad developers to sell turnkey based client/server applications that use multiple iPads talking to a central Time Capsule device. This means for Apple, that it could sell combinations of iPads and Time Capsules.

This may be attractive for small/mid-size businesses where having multiple iPads talking to a central database server is an improvement over their paper-based (and sneaker-net or word-of-mouth) system. The TCO would be relatively low, given the turnkey nature of the iPad and Time Capsule.

Some example costs:

Time Capsule: $300
Four iPads: $2000
Setup Time: 1 hour
Software per iPad: $1-$100, depending on functionality in the Application and App Store competition
Training: None -1 hour, depending on if the User already has an iPhone.

The cost of software per iPad is interesting, since the long-tail effect would almost guarantee that the price will approach $1.

I reviewed the software development kit APIs for the new iPad. The new APIs have a lot more functionality than what is available with the iPhone SDK. Anyone considering the iPad as being ‘an oversized iPod Touch is only considering the physical form factor, most likely they have not yet reviewed the iPad native SDK.

I think, given the new APIs, the native apps for the iPad will be a new class in itself (targeting the full multi-touch metaphor). I would conjecture that, in the near future, application developers will target the iPad as their primary platform and begin to consider iPhone apps as their apps’s mobile version, with limited functionality and limited screen space.

More articles to come, covering iPhone and iPad development.

System Agent AI “Agent Smith” is now online!

In case you didn’t know, the Agents are there to keep order and prevent the Players from becoming ‘Neo’ and hacking the game world, from inside. NPC System Agents will patrol the system looking for anomalies and punish those that attempt to overthrow or hack the game world.

Daimoku Multi-Programmer Online is an environment written in Ruby and ActiveRecord and implemented using Why’s Freaky-Freaky Sandbox. Daimoku allows multiple Ruby programmers to chat, share code and objects in real-time in an EW-Two-style environment.

Visit http://daimoku.elitefrontier.org for more information

If you maintain various virtual domains on a Debian Lenny box you can use Apple’s mail.app to access each virtual domain so you can send/receive e-mail as different users on those virtual domains. I use mail.app to access many virtual domains, on a daily basis and it works pretty well. This short article, describes how to set up the server correctly.

Install Courier with IMAP and IMAP SSL. If you want to be somewhat secure, only install the courier-imap-ssl. When you are prompted if you want to set up the web configuration directories, select NO.

apt-get install courier-imap courier-imap-ssl

If you are running mailx, you’ll need to install the mailbox conversion program

apt-get install  mb2md

Create the Courier mail directory, using maildirmake

su - myuser
cd /home/myuser
maildirmake Maildir

Convert the contents of the current mbox to the Maildir

su - myuser
mb2md -s /home/myuser/mbox -d /home/myuser/Maildir

For future incoming e-mail, let the email go into mbox, but put a copy into Maildir, create a .procmailrc with the following:

MAILDIR=$HOME/Maildir
:0c 
$MAILDIR/

Daimoku Multi-Programmer Online is an environment written in Ruby and ActiveRecord and implemented using Why’s Freaky-Freaky Sandbox. Daimoku allows multiple Ruby programmers to chat, share code and objects in real-time in an EW-Two-style environment.

System Agent AIs

NPC System Agents are now online. The only thing left is to program their AI to look for game world anomalies.

In case you didn’t know, the Agents are there to keep order and prevent the Players from becoming ‘Neo’ and hacking the game world, from inside. NPC System Agents will patrol the system looking for anomalies and punish those that attempt to overthrow or hack the game world.



Alpha Testers Wanted

If you’re interested in being an alpha tester and messing around with the system, send an e-mail to [rdegraci @ gmail com] with the subject “Request Daimoku Alpha Test”.

Any questions? Just ask in the comments.

The default clean installation of Snow Leopard uses the en_US.us-ascii locale. Unfortunately, when installing postgresql 8.3 using macports, the installer will complain when initializing the database, for example:

sudo su postgres -c '/opt/local/lib/postgresql83/bin/initdb 
-D /opt/local/var/db/postgresql83/defaultdb'

You will get the following error

The database cluster will be initialized with locale en_US.us-ascii.
could not determine encoding for locale "en_US.us-ascii": codeset is "us-ascii" 
initdb: could not find suitable encoding for locale en_US.us-ascii
Rerun initdb with the -E option.
Try "initdb --help" for more information.

The solution is to change the locale. First we list the locales available:

Outrun:db rdegraci$ locale -a | grep en_US
en_US
en_US.ISO8859-1
en_US.ISO8859-15
en_US.US-ASCII
en_US.UTF-8

Now we set the locale to en_US.UTF-8

Outrun:~ rdegraci$ export LC_ALL=en_US.UTF-8
Now start the server
Outrun:~ rdegraci$ sudo su postgres -c '/opt/local/lib/postgresql83/bin/initdb 
-D /opt/local/var/db/postgresql83/defaultdb'
You should get the following output
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale en_US.UTF-8.
The default database encoding has accordingly been set to UTF8.
The default text search configuration will be set to "english".

fixing permissions on existing directory /opt/local/var/db/postgresql83/defaultdb ... ok
creating subdirectories ... ok
selecting default max_connections ... 20
selecting default shared_buffers/max_fsm_pages ... 1600kB/20000
creating configuration files ... ok
creating template1 database in /opt/local/var/db/postgresql83/defaultdb/base/1 ... ok
initializing pg_authid ... ok
initializing dependencies ... ok
creating system views ... ok
loading system objects' descriptions ... ok
creating conversions ... ok
creating dictionaries ... ok
setting privileges on built-in objects ... ok
creating information schema ... ok
vacuuming database template1 ... ok
copying template1 to template0 ... ok
copying template1 to postgres ... ok

A quick and dirty way of setting up Rails and Apache2, is using Apache’s balancer module. You’ll need to enable the proxy module, and the proxy balancer module and then setup the configuration, as follows:

Set up the load balancer, to forward requests to the localhost, port 4040

<proxy balancer://my_site.com>
        BalancerMember http://127.0.0.1:4040
        Order allow,deny
        Allow from all
</proxy>

Configure the virtual host to point to the Rails Application’s root directory, located at /var/www/my_site.com.site/

<VirtualHost *:80>
        ServerAdmin hostmaster@my_site.com

        ServerName my_site.com 
        ServerAlias www.my_site.com

        DocumentRoot /var/www/my_site.com.site/

        ErrorLog /var/log/apache2/error_my_site.com.log

        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn

        CustomLog /var/log/apache2/access_my_site.com.log combined

        ProxyPass / balancer://my_site.com/
        ProxyPassReverse / balancer://my_site.com/
        ProxyPreserveHost on
        ProxyPass /images !
        ProxyPass /stylesheets !

        Alias /images /var/www/my_site.com.site/public/images
        Alias /stylesheets /var/www/my_site.com.site/public/stylesheets

</VirtualHost>

Start the Rails app to listen on localhost, port 4040. Finally restart the Apache server. If all goes well, the Apache server will forward requests to the Rails app.

From an OS to a Conversation

December 1st, 2009

A deeper view of Google Wave suggests that Google may want to change how people converse (via Google Wave) and thereby build a platform of tools to let people manage how they converse.

The File Metaphor become a Conversation Metaphor and the concept of “OS” becomes “Tools to manage the Conversation.”

Continuing this idea, means…

  • File Copy becomes “a tool to copy Conversations”
  • File Diff becomes “a tool to diff Conversations”
  • File Delete becomes”a tool to delete Waves”
  • Folders become “a tool to group Conversations”
  • File Search becomes “a tool to search Conversations”

Possible innovation

  • Searching across Waves for common ideas and connecting people based upon those connections
  • The concept of Peripherals becomes “Devices that can understand Conversations”

An exciting idea

The idea of “Devices that can understand Conversations” is very exciting and that can possibly be the next set of innovations from Google, since they are already in-place with mobile devices.

A little bit of this and that

November 30th, 2009

Back in 2002, I started writing C++ with a unique style of combining Modern C++ Design and Domain Driven Design. My endeavor was to write a 3D game engine. It was a fun exercise.

First, define the Math Trait. We will use the Real Number System


template <typename T>
struct RealNumberSystem
{
    //3 tuple Reals
    static int const N=3;    

    typedef T Radian;
    typedef T Theta;
    typedef T Rho;
    typedef T Radius;
    typedef T Scalar;
};

Next, define the Geometry Trait. We will use Standard Euclidean. The Tuple4 typedef is interesting.


struct StandardEuclidean
{
    static int const RightHanded=1;
    static int const LeftHanded=0;

    typedef Vector1x3<float> RowVector;
    typedef Vector3x1<float> ColumnVector;
    typedef Matrix3x3<float> Matrix3;

    typedef ColumnVector Origin;
    typedef ColumnVector Axis;
    typedef ColumnVector AnyVector;
    typedef ColumnVector ComponentVector;
    typedef Matrix3    Basis;

    typedef ColumnVector Point;
    typedef ColumnVector Normal;
    typedef ColumnVector Direction;

    //Four dimensions
    typedef Vector<float,4,1,Storage2Dim> Tuple4;

};

The following is the most critical class, which I think is the linch-pin that holds the math and the geometry together. Without this class, there is NO mathematical representation of a geometrical point, therefore the domain semantics within the code would eventually break down. I think this is the most conceptually beautiful code I have ever written:

//Mathematical representation of Geometrical Point

#include "Vector.h" 

template <typename T>
class Cartesian : public Vector3x1<T>
{
public:

    Cartesian(T x, T y, T z) : Vector3x1<T>(x,y,z)
    {
    }
};

Finally, define the Coordinate Systems and transformations between the systems

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//CoordinateSystem Template Class Declaration

template <typename T,
          template <typename T1> class MathTrait=RealNumberSystem,
          typename GeometryTrait=StandardEuclidean>
class Cartesian3DCoordinateSystem
{
public:
    //Direct Access
    typename GeometryTrait::Axis m_U[MathTrait<T>::N];
    typename GeometryTrait::Origin m_P;

    Cartesian3DCoordinateSystem()
    {
        if(GeometryTrait::RightHanded)
        {
            m_P.Set(0,0,0);
            m_U[0].Set(1,0,0);
            m_U[1].Set(0,1,0);
            m_U[2].Set(0,0,1);
        }
        else
        {
            m_P.Set(0,0,0);
            m_U[0].Set(0,0,1);
            m_U[1].Set(0,1,0);
            m_U[2].Set(1,0,0);
        }
    }

    //Create this Coordinate System's Basis to match X
    Cartesian3DCoordinateSystem(const typename GeometryTrait::AnyVector& X)
    {
        if(GeometryTrait::RightHanded)
        {
            m_P.Set(0,0,0);
            m_U[0].Set(1,0,0);
            m_U[1].Set(0,1,0);
            m_U[2].Set(0,0,1);
        }
        else
        {
            m_P.Set(0,0,0);
            m_U[0].Set(0,0,1);
            m_U[1].Set(0,1,0);
            m_U[2].Set(1,0,0);
        }

        typename MathTrait<T>::Scalar Y[MathTrait::N]={0};
        for (int i=0; i<MathTrait<T>::N; ++i);
        {
            Y[i]=VectorColumn3::Dot(m_U[i],(X-m_P));
            m_U[i]*=Y[i];
        }

    }

    typename GeometryTrait::Basis GetBasis()
    {
        typename GeometryTrait::Basis R(m_U[0],m_U[1],m_U[2]);
        return R;
    }
};

template <typename T,
          template <typename> class MathTrait,
          typename GeometryTrait>
Vector3x1<T> Cylindrical2Cartesian(const CylindricalCoordinateSystem<T,MathTrait,GeometryTrait>& c)
{
    //m_Angle must be in Radians
    return (Vector3x1<float>((c.m_R*sin(c.m_Angle)),(c.m_R*cos(c.m_Angle)),0)); 
}

template <typename T,
          template <typename T> class MathTrait=RealNumberSystem,
          typename GeometryTrait=StandardEuclidean>
class CylindricalCoordinateSystem
{
public:
    //Direct Access
    typename GeometryTrait::Origin m_Z;
    typename MathTrait<T>::Theta m_Angle;
    typename MathTrait<T>::Radius m_R;    //Radians

    CylindricalCoordinateSystem()
    {
        m_Angle=T();
        m_R=T();
    }

    void SetAngleDegrees(T angle)
    {
        const float pi=3.141592653f;
        const float radconv=pi/180;
        m_Angle=angle*radconv;
    }

    //The axis parameters are perpendicular
    CylindricalCoordinateSystem(T x, T y, typename GeometryTrait::Origin Z)
    {
        //x and y are relative to Z
        x=Z.x-x;
        y=Z.y=y;

        m_R=sqrt((pow(x,2)+pow(y,2)));
        m_Angle=(acos(x/m_R));
        if(y<=0) m_Angle=-m_Angle;
    }
};

template <typename T,
          template <typename T> class MathTrait,
          typename GeometryTrait>
Vector3x1<T> Spherical2Cartesian(const SphericalCoordinateSystem<T,MathTrait,GeometryTrait>& c)
{
    return (Vector3x1<float>((c.m_R*sin(c.m_PolarAngle)*cos(c.m_Azimuth)),(c.m_R*sin(c.m_PolarAngle)*cos(c.m_Azimuth)),(c.m_R*cos(c.m_PolarAngle)))); 
}

template <typename T,
          template <typename T1> class MathTrait=RealNumberSystem,
          typename GeometryTrait=StandardEuclidean>
class SphericalCoordinateSystem
{
public:
    //Direct Access
    typename MathTrait<T>::Radius m_R;
    typename MathTrait<T>::Theta m_Azimuth;
    typename MathTrait<T>::Rho m_PolarAngle;

    SphericalCoordinateSystem(typename GeometryTrait::Point P)
    {
        m_R=sqrt((pow(P.x,2)+pow(P.y,2)+pow(P.z,2)));
        m_PolarAngle=acos(P.z/m_R);
        m_Azimuth=acos(x/(sqrt(pow(P.x,2)+pow(P.y,2))));
    }
};

Define a linear component and a plane. I often wonder how things would be different, if we used: typename GeometryTrait = NonEuclidean

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//LinearComponent Template Class Definition

template <typename T,
          typename GeometryTrait=StandardEuclidean>
class LinearComponent
{
public:
    //Direct access
    typename GeometryTrait::Point m_B;
    typename GeometryTrait::ColumnVector m_M;

    LinearComponent(typename const GeometryTrait::Point& B, typename const GeometryTrait::ColumnVector& M) : 
    m_B(B), m_M(M)
    {
        m_M.Normalize();
    }
};

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//Plane Template Class Definition

template <typename T,
          typename GeometryTrait=StandardEuclidean>
class Plane
{

public:
    //Three dimensional representation
    typename GeometryTrait::Point m_P;
    typename GeometryTrait::Normal m_N;

    //Four dimensional representation
    typename GeometryTrait::Tuple4    m_ND;    // <N,D>

    Plane() : m_P(),m_N() 
    {

    }

    Plane(const T& px, const T& py, const T& pz,
          const T& nx, const T& ny, const T& nz, const T& d) : m_P(px,py,pz),m_N(nx,ny,nz),m_ND(nx,ny,nz,d)
    {
        m_N.Normalize();

        assert( (Vector<float,3,1>::Dot(m_N,m_P) + (m_ND.m_Storage.M[3][0])==0));
    }

    Plane(const T& A, const T& B, const T& C, const T& D) : m_N(A,B,C), m_P(), m_ND(A,B,C,D)
    {
        assert(m_N.Magnitude()>0);

        (m_ND.m_Storage.M[3][0])/=m_N.Magnitude();
        m_N.Normalize();

        //Create a dummy Point
        m_P=m_N * -m_ND.m_Storage.M[3][0];

        //D==-(N dot P)
        T ndotp=(Vector<T,3,1>::Dot(m_N,m_P));
        T d=m_ND.m_Storage.M[3][0];
        assert(fabs(d + ndotp) < 0.001f); 

        // N dot P + D == 0
        T dd=(Vector<T,3,1>::Dot(m_N,m_P) + (m_ND.m_Storage.M[3][0]));
        assert(fabs(dd) < 0.001f);    //dd==zero
    }

    void SetNormal(const T& x, const T& y, const T& z)
    {
        m_N.Set(x,y,z);

        m_N.Normalize();

        m_ND.Set(m_N.x,m_N.y,m_N.z,0);    //Direction
    }

    void SetPoint(const T& x, const T& y, const T& z)
    {
        m_P.Set(x,y,z);
    }

    void SetD(const T& d)
    {
        m_ND.m_Storage.M[3][0]=d;
    }

    T GetD() const
    {
        return m_ND.m_Storage.M[3][0];
    }

    Plane(typename const GeometryTrait::Point& P, typename const GeometryTrait::Normal& N) : m_P(P), m_N(N)
    {
        //Make calculations easier by normalizing
        m_N.Normalize();

        m_ND.Set(N.x,N.y,N.z,-(Vector<float,3,1>::Dot(m_N,P)));

        assert( (Vector<float,3,1>::Dot(m_N,m_P) + (m_ND.m_Storage.M[3][0])==0));
    }
};

I’ve left out the Matrix template and Vector template code, since it’s pretty boring.

Hyper-Meta-Protocol

November 18th, 2009

Twitter is an informal protocol for transferring ideas and opinions in extremely compact form. Interestingly, Humans have adapted to the protocol, instead of the protocol adapting to Humans. These User-created protocols ride on top of of Twitter and are adopted by other Twitter users, if found useful.

Meta Protocol?

If we consider this informal protocol for a moment, we start to realize the protocols can be considered a Hyper-Meta-Protocol (HMP) or a protocol that is extensible but can also define itself.

Mechanization

So let’s try to mechanize the adoption of meta-protocols that ride on top of a particular protocol:

1) A protocol is essentially the process of synchronizing two or more state machines and optionally, transferring information between two or more two state machines.

2) Given the definition of protocol, we can constrain state machine changes such that those changes can be synchronized between the two or more separate state machines and therefore create different state-machines pairs, maintaining different meta-protocol sessions.

3) We reconcile differences or contradictions between different Users of the protocol, by performing squelching of non-popular meta-protocol sessions at the server level..

Some properties

  • Stateful

    HMPs are stateful, in that an HMP is implemented by a State Machine

  • In-Band

    HMPs are recursively in-band capable. That is to say, an HMP may contain another in-band HMP.

  • In-Band Modification

    In-band HMP/State-Machine may inspect/modify the containing HMP, but only if the containing HMP/State-Machine allows.

Humanity Friendly Technology

November 9th, 2009

Humanity Friendly Technology (HFT) is a term that describes technology that helps to mitigate the flaws of Humanity, especially our short-term thinking and our selfish nature.

The current state of Technology not as friendly to humanity as one would think, since he design of technology is based upon the profit/cost ratio. We have to remember that the profit/cost ratio (a construct of the corporation) has no relation to improving the quality of Humanity itself.

Fundamental Information System Design

If the following items have not been achieved, the Information System is fundamentally flawed.

  • Information must be difficult to destroy
  • The Information System must be automatically redundant (minimal human maintenance is required)

A good example of a Humanity Friendly Information System would be the Western Digital My Book World Edition II NAS with 4TB (two 2TB disks) with out of the box RAID mirroring, along with support for Time Machine and file versioning.

Technology Design

Technology that does not mitigate the worse case and support the best case, is fundamentally flawed.

  • Technology must mitigate the worse case (prevent destruction of itself or by its design prevent human death or injury)
  • Technology must support the best case (self diagnosis of its system or by its design improve the quality of life of humans)

An example of Humanity Friendly Technology Design would be the Tesla Roadster Battery System

Artificial Intelligence Design

If preventing human death or injury has not been achieved, the AI is fundamentally flawed.

  • AI must, by its design, prevent human death or injury
  • AI must, by its design, ensure the replication and redundancy of information

An example of Humanity Friendly AI Design would be the Volvo Collision Warning System.

Power Systems Design

Power systems that enslave humanity to its maintenance or pollutes the biosphere is fundamentally flawed.

  • Power Systems, must by design, be self maintaining (minimal to no human maintenance is required)
  • Power Systems must be non polluting to the biosphere
  • Power Systems must be distributed at no cost or at low cost to the public.

An example of a Humanity Friendly Power System would be the Westinghouse AP 1000 Nuclear Power Plant which is designed to be passively safe, even with no operator action and a complete loss of all on-site and off-site ac power, the AP1000 will safely shut down and remain cool.