2018-10-16 23:09:25 +02:00
//
2019-01-04 23:36:51 +01:00
// C o p y r i g h t ( c ) 2 0 1 9 O p e n W h i s p e r S y s t e m s . A l l r i g h t s r e s e r v e d .
2018-10-16 23:09:25 +02:00
//
import Foundation
// / F a c t o r i e s f o r c r e a t i n g s o m e d e f a u l t T S Y a p D a t a b a s e O b j e c t s .
// /
// / T o c u s t o m i z e p r o p e r t i e s a p p l i e d b y t h e f a c t o r y ( e . g . ` s o m e P r o p e r t y ` )
2018-12-18 00:48:15 +01:00
// / t h e f a c t o r y n e e d s a ` p u b l i c v a r s o m e P r o p e r t y B u i l d e r : ( ) - > ( S o m e P r o p e r t y T y p e ) `
2018-10-16 23:09:25 +02:00
// / w h i c h i s t h e n u s e d i n t h e ` c r e a t e ` m e t h o d .
// /
// / E x a m p l e s :
// /
// / C r e a t e o n e e m p t y t h r e a d :
// /
// / l e t o n e T h r e a d = C o n t a c t T h r e a d F a c t o r y ( ) . c r e a t e ( )
// /
// / C r e a t e 1 2 t h r e a d ' s w i t h 1 0 0 m e s s a g e s e a c h
// /
// / l e t f a c t o r y = C o n t r a c t T h r e a d F a c t o r y ( )
// / f a c t o r y . m e s s a g e C o u n t = 1 0 0
// / f a c t o r y . c r e a t e ( c o u n t : 1 2 )
// /
// / C r e a t e 1 0 0 m e s s a g e s i n a n e x i s t i n g t h r e a d
// /
// / l e t e x i s t i n g T h r e a d : T S T h r e a d = g e t S o m e E x i s t i n g T h r e a d ( )
// / l e t m e s s a g e F a c t o r y = T S I n c o m i n g M e s s a g e F a c t o r y ( )
// / m e s s a g e F a c t o r y . t h r e a d C r e a t o r = { _ i n r e t u r n e x i s t i n g T h r e a d }
// / m e s s a g e F a c t o r y . c r e a t e ( c o u n t : 1 0 0 )
// /
2018-12-18 00:48:15 +01:00
public protocol Factory {
2018-10-16 23:09:25 +02:00
associatedtype ObjectType : TSYapDatabaseObject
var dbConnection : YapDatabaseConnection { get }
func readWrite ( block : @ escaping ( YapDatabaseReadWriteTransaction ) -> Void )
// MARK: F a c t o r y M e t h o d s
func create ( ) -> ObjectType
func create ( transaction : YapDatabaseReadWriteTransaction ) -> ObjectType
func create ( count : UInt ) -> [ ObjectType ]
func create ( count : UInt , transaction : YapDatabaseReadWriteTransaction ) -> [ ObjectType ]
}
2018-12-18 00:48:15 +01:00
public extension Factory {
2018-11-10 00:56:59 +01:00
2018-12-18 00:48:15 +01:00
static public var dbConnection : YapDatabaseConnection {
2018-11-10 00:56:59 +01:00
return OWSPrimaryStorage . shared ( ) . dbReadWriteConnection
}
2018-12-18 00:48:15 +01:00
public var dbConnection : YapDatabaseConnection {
2018-10-16 23:09:25 +02:00
return OWSPrimaryStorage . shared ( ) . dbReadWriteConnection
}
2018-12-18 00:48:15 +01:00
static public func readWrite ( block : @ escaping ( YapDatabaseReadWriteTransaction ) -> Void ) {
2018-11-10 00:56:59 +01:00
dbConnection . readWrite ( block )
}
2018-12-18 00:48:15 +01:00
public func readWrite ( block : @ escaping ( YapDatabaseReadWriteTransaction ) -> Void ) {
2018-10-16 23:09:25 +02:00
dbConnection . readWrite ( block )
}
// MARK: F a c t o r y M e t h o d s
2018-12-18 00:48:15 +01:00
public func create ( ) -> ObjectType {
2018-10-16 23:09:25 +02:00
var item : ObjectType !
self . readWrite { transaction in
item = self . create ( transaction : transaction )
}
return item
}
2018-12-18 00:48:15 +01:00
public func create ( count : UInt ) -> [ ObjectType ] {
2018-10-16 23:09:25 +02:00
var items : [ ObjectType ] = [ ]
self . readWrite { transaction in
items = self . create ( count : count , transaction : transaction )
}
return items
}
2018-12-18 00:48:15 +01:00
public func create ( count : UInt , transaction : YapDatabaseReadWriteTransaction ) -> [ ObjectType ] {
2018-10-16 23:09:25 +02:00
return ( 0. . < count ) . map { _ in return create ( transaction : transaction ) }
}
}
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public class ContactThreadFactory : NSObject , Factory {
2018-10-16 23:09:25 +02:00
var messageCount : UInt = 0
// MARK: F a c t o r y
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public func create ( transaction : YapDatabaseReadWriteTransaction ) -> TSContactThread {
2018-10-16 23:09:25 +02:00
let threadId = generateContactThreadId ( )
let thread = TSContactThread . getOrCreateThread ( withContactId : threadId , transaction : transaction )
let incomingMessageFactory = IncomingMessageFactory ( )
incomingMessageFactory . threadCreator = { _ in return thread }
let outgoingMessageFactory = OutgoingMessageFactory ( )
outgoingMessageFactory . threadCreator = { _ in return thread }
( 0. . < messageCount ) . forEach { _ in
2018-10-16 20:04:10 +02:00
if [ true , false ] . ows_randomElement ( ) ! {
2018-10-16 23:09:25 +02:00
_ = incomingMessageFactory . create ( transaction : transaction )
} else {
_ = outgoingMessageFactory . create ( transaction : transaction )
}
}
return thread
}
// MARK: G e n e r a t o r s
2018-12-18 00:48:15 +01:00
public func generateContactThreadId ( ) -> String {
2018-10-16 23:09:25 +02:00
return CommonGenerator . contactId
}
}
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public class OutgoingMessageFactory : NSObject , Factory {
2018-10-16 23:09:25 +02:00
// MARK: F a c t o r y
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public func build ( transaction : YapDatabaseReadWriteTransaction ) -> TSOutgoingMessage {
2018-10-16 23:09:25 +02:00
let item = TSOutgoingMessage ( outgoingMessageWithTimestamp : timestampBuilder ( ) ,
in : threadCreator ( transaction ) ,
messageBody : messageBodyBuilder ( ) ,
2018-11-10 00:56:59 +01:00
attachmentIds : attachmentIdsBuilder ( ) ,
expiresInSeconds : expiresInSecondsBuilder ( ) ,
expireStartedAt : expireStartedAtBuilder ( ) ,
isVoiceMessage : isVoiceMessageBuilder ( ) ,
groupMetaMessage : groupMetaMessageBuilder ( ) ,
quotedMessage : quotedMessageBuilder ( ) ,
2019-01-14 17:00:24 +01:00
contactShare : contactShareBuilder ( ) ,
linkPreview : linkPreviewBuilder ( ) )
2018-10-17 06:10:43 +02:00
return item
}
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public func create ( transaction : YapDatabaseReadWriteTransaction ) -> TSOutgoingMessage {
2018-10-17 06:10:43 +02:00
let item = self . build ( transaction : transaction )
2018-10-16 23:09:25 +02:00
item . save ( with : transaction )
return item
}
// MARK: D e p e n d e n t F a c t o r i e s
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public var threadCreator : ( YapDatabaseReadWriteTransaction ) -> TSThread = { transaction in
2018-10-16 23:09:25 +02:00
ContactThreadFactory ( ) . create ( transaction : transaction )
}
// MARK: G e n e r a t o r s
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public var timestampBuilder : ( ) -> UInt64 = {
2018-10-16 23:09:25 +02:00
return NSDate . ows_millisecondTimeStamp ( )
}
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public var messageBodyBuilder : ( ) -> String = {
2018-10-16 23:09:25 +02:00
return CommonGenerator . paragraph
}
2018-10-17 06:10:43 +02:00
2018-11-10 00:56:59 +01:00
@objc
var attachmentIdsBuilder : ( ) -> NSMutableArray = {
return [ ]
}
@objc
2018-12-18 00:48:15 +01:00
public var expiresInSecondsBuilder : ( ) -> UInt32 = {
2018-11-10 00:56:59 +01:00
return 0
}
@objc
2018-12-18 00:48:15 +01:00
public var expireStartedAtBuilder : ( ) -> UInt64 = {
2018-11-10 00:56:59 +01:00
return 0
}
@objc
2018-12-18 00:48:15 +01:00
public var isVoiceMessageBuilder : ( ) -> Bool = {
2018-11-10 00:56:59 +01:00
return false
}
@objc
2018-12-18 00:48:15 +01:00
public var groupMetaMessageBuilder : ( ) -> TSGroupMetaMessage = {
2018-11-10 00:56:59 +01:00
return . unspecified
}
@objc
2018-12-18 00:48:15 +01:00
public var quotedMessageBuilder : ( ) -> TSQuotedMessage ? = {
2018-11-10 00:56:59 +01:00
return nil
}
@objc
2018-12-18 00:48:15 +01:00
public var contactShareBuilder : ( ) -> OWSContact ? = {
2018-11-10 00:56:59 +01:00
return nil
}
2019-01-14 17:00:24 +01:00
@objc
public var linkPreviewBuilder : ( ) -> OWSLinkPreview ? = {
return nil
}
2018-10-17 06:10:43 +02:00
// MARK: D e l i v e r y R e c e i p t s
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public func buildDeliveryReceipt ( ) -> OWSReceiptsForSenderMessage {
2018-10-17 06:10:43 +02:00
var item : OWSReceiptsForSenderMessage !
self . readWrite { transaction in
item = self . buildDeliveryReceipt ( transaction : transaction )
}
return item
}
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public func buildDeliveryReceipt ( transaction : YapDatabaseReadWriteTransaction ) -> OWSReceiptsForSenderMessage {
2018-10-17 06:10:43 +02:00
let item = OWSReceiptsForSenderMessage . deliveryReceiptsForSenderMessage ( with : threadCreator ( transaction ) ,
messageTimestamps : messageTimestampsBuilder ( ) )
return item
}
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public var messageTimestampsBuilder : ( ) -> [ NSNumber ] = {
2018-10-17 06:10:43 +02:00
return [ 1 ]
}
2018-10-16 23:09:25 +02:00
}
2018-11-10 00:56:59 +01:00
@objc
2019-01-18 01:35:45 +01:00
public class IncomingMessageFactory : NSObject , Factory {
2018-10-16 23:09:25 +02:00
// MARK: F a c t o r y
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public func create ( transaction : YapDatabaseReadWriteTransaction ) -> TSIncomingMessage {
2019-01-18 18:54:09 +01:00
let thread = threadCreator ( transaction )
2018-10-16 23:09:25 +02:00
let item = TSIncomingMessage ( incomingMessageWithTimestamp : timestampBuilder ( ) ,
2019-01-18 18:54:09 +01:00
in : thread ,
authorId : authorIdBuilder ( thread ) ,
2018-11-10 00:56:59 +01:00
sourceDeviceId : sourceDeviceIdBuilder ( ) ,
2018-10-16 23:09:25 +02:00
messageBody : messageBodyBuilder ( ) ,
2018-11-10 00:56:59 +01:00
attachmentIds : attachmentIdsBuilder ( ) ,
expiresInSeconds : expiresInSecondsBuilder ( ) ,
quotedMessage : quotedMessageBuilder ( ) ,
contactShare : contactShareBuilder ( ) ,
2019-01-14 17:00:24 +01:00
linkPreview : linkPreviewBuilder ( ) ,
2018-11-10 00:56:59 +01:00
serverTimestamp : serverTimestampBuilder ( ) ,
wasReceivedByUD : wasReceivedByUDBuilder ( ) )
2018-10-16 23:09:25 +02:00
item . save ( with : transaction )
return item
}
// MARK: D e p e n d e n t F a c t o r i e s
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public var threadCreator : ( YapDatabaseReadWriteTransaction ) -> TSThread = { transaction in
2018-10-16 23:09:25 +02:00
ContactThreadFactory ( ) . create ( transaction : transaction )
}
// MARK: G e n e r a t o r s
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public var timestampBuilder : ( ) -> UInt64 = {
2018-10-16 23:09:25 +02:00
return NSDate . ows_millisecondTimeStamp ( )
}
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public var messageBodyBuilder : ( ) -> String = {
2018-10-16 23:09:25 +02:00
return CommonGenerator . paragraph
}
2018-11-10 00:56:59 +01:00
@objc
2019-01-18 18:54:09 +01:00
public var authorIdBuilder : ( TSThread ) -> String = { thread in
switch thread {
case let contactThread as TSContactThread :
return contactThread . contactIdentifier ( )
case let groupThread as TSGroupThread :
return groupThread . recipientIdentifiers . ows_randomElement ( ) ? ? CommonGenerator . contactId
default :
owsFailDebug ( " unexpected thread type " )
return CommonGenerator . contactId
}
2018-10-16 23:09:25 +02:00
}
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public var sourceDeviceIdBuilder : ( ) -> UInt32 = {
2018-11-10 00:56:59 +01:00
return 1
}
@objc
2018-12-18 00:48:15 +01:00
public var attachmentIdsBuilder : ( ) -> [ String ] = {
2018-11-10 00:56:59 +01:00
return [ ]
}
@objc
2018-12-18 00:48:15 +01:00
public var expiresInSecondsBuilder : ( ) -> UInt32 = {
2018-11-10 00:56:59 +01:00
return 0
}
@objc
2018-12-18 00:48:15 +01:00
public var quotedMessageBuilder : ( ) -> TSQuotedMessage ? = {
2018-11-10 00:56:59 +01:00
return nil
}
@objc
2018-12-18 00:48:15 +01:00
public var contactShareBuilder : ( ) -> OWSContact ? = {
2018-11-10 00:56:59 +01:00
return nil
}
2019-01-14 17:00:24 +01:00
@objc
public var linkPreviewBuilder : ( ) -> OWSLinkPreview ? = {
return nil
}
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public var serverTimestampBuilder : ( ) -> NSNumber ? = {
2018-11-10 00:56:59 +01:00
return nil
}
@objc
2018-12-18 00:48:15 +01:00
public var wasReceivedByUDBuilder : ( ) -> Bool = {
2018-11-10 00:56:59 +01:00
return false
}
2018-10-16 23:09:25 +02:00
}
2018-11-10 00:56:59 +01:00
@objc
class GroupThreadFactory : NSObject , Factory {
2018-10-16 23:09:25 +02:00
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public var messageCount : UInt = 0
2018-10-16 23:09:25 +02:00
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public func create ( transaction : YapDatabaseReadWriteTransaction ) -> TSGroupThread {
2018-10-16 23:09:25 +02:00
let thread = TSGroupThread . getOrCreateThread ( with : groupModelBuilder ( self ) ,
transaction : transaction )
thread . save ( with : transaction )
let incomingMessageFactory = IncomingMessageFactory ( )
incomingMessageFactory . threadCreator = { _ in return thread }
let outgoingMessageFactory = OutgoingMessageFactory ( )
outgoingMessageFactory . threadCreator = { _ in return thread }
( 0. . < messageCount ) . forEach { _ in
2018-10-16 20:04:10 +02:00
if [ true , false ] . ows_randomElement ( ) ! {
2018-10-16 23:09:25 +02:00
_ = incomingMessageFactory . create ( transaction : transaction )
} else {
_ = outgoingMessageFactory . create ( transaction : transaction )
}
}
return thread
}
// MARK: G e n e r a t o r s
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public var groupModelBuilder : ( GroupThreadFactory ) -> TSGroupModel = { groupThreadFactory in
2018-10-16 23:09:25 +02:00
return TSGroupModel ( title : groupThreadFactory . titleBuilder ( ) ,
memberIds : groupThreadFactory . memberIdsBuilder ( ) ,
image : groupThreadFactory . imageBuilder ( ) ,
groupId : groupThreadFactory . groupIdBuilder ( ) )
}
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public var titleBuilder : ( ) -> String ? = {
2018-10-16 23:09:25 +02:00
return CommonGenerator . words ( count : 3 )
}
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public var groupIdBuilder : ( ) -> Data = {
2018-10-16 23:09:25 +02:00
return Randomness . generateRandomBytes ( Int32 ( kGroupIdLength ) ) !
}
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public var imageBuilder : ( ) -> UIImage ? = {
2018-10-16 23:09:25 +02:00
return nil
}
2018-11-10 00:56:59 +01:00
@objc
2018-12-18 00:48:15 +01:00
public var memberIdsBuilder : ( ) -> [ RecipientIdentifier ] = {
2018-10-16 20:04:10 +02:00
let groupSize = arc4random_uniform ( 10 )
2018-10-16 23:09:25 +02:00
return ( 0. . < groupSize ) . map { _ in CommonGenerator . contactId }
}
}
2018-11-10 00:56:59 +01:00
@objc
class AttachmentStreamFactory : NSObject , Factory {
@objc
2018-12-18 00:48:15 +01:00
class public func create ( contentType : String , dataSource : DataSource ) -> TSAttachmentStream {
2018-11-10 00:56:59 +01:00
var item : TSAttachmentStream !
readWrite { transaction in
item = create ( contentType : contentType , dataSource : dataSource , transaction : transaction )
}
return item
}
@objc
2018-12-18 00:48:15 +01:00
class public func create ( contentType : String , dataSource : DataSource , transaction : YapDatabaseReadWriteTransaction ) -> TSAttachmentStream {
2018-11-10 00:56:59 +01:00
let factory = AttachmentStreamFactory ( )
factory . contentTypeBuilder = { return contentType }
factory . byteCountBuilder = { return UInt32 ( dataSource . dataLength ( ) ) }
2019-01-04 23:36:51 +01:00
factory . sourceFilenameBuilder = { return dataSource . sourceFilename ? ? " fake-filename.dat " }
2018-11-10 00:56:59 +01:00
let attachmentStream = factory . build ( transaction : transaction )
dataSource . write ( toPath : attachmentStream . originalFilePath ! )
attachmentStream . save ( with : transaction )
return attachmentStream
}
// MARK: F a c t o r y
@objc
2018-12-18 00:48:15 +01:00
public func create ( transaction : YapDatabaseReadWriteTransaction ) -> TSAttachmentStream {
2018-11-10 00:56:59 +01:00
let attachmentStream = build ( transaction : transaction )
attachmentStream . save ( with : transaction )
return attachmentStream
}
@objc
2018-12-18 00:48:15 +01:00
public func build ( transaction : YapDatabaseReadTransaction ) -> TSAttachmentStream {
2018-11-10 00:56:59 +01:00
return build ( )
}
@objc
2018-12-18 00:48:15 +01:00
public func build ( ) -> TSAttachmentStream {
2018-11-10 00:56:59 +01:00
let attachmentStream = TSAttachmentStream ( contentType : contentTypeBuilder ( ) ,
byteCount : byteCountBuilder ( ) ,
sourceFilename : sourceFilenameBuilder ( ) ,
caption : captionBuilder ( ) ,
albumMessageId : albumMessageIdBuilder ( ) )
return attachmentStream
}
// MARK: P r o p e r t i e s
@objc
2018-12-18 00:48:15 +01:00
public var contentTypeBuilder : ( ) -> String = {
2018-11-10 00:56:59 +01:00
return OWSMimeTypeApplicationOctetStream
}
@objc
2018-12-18 00:48:15 +01:00
public var byteCountBuilder : ( ) -> UInt32 = {
2018-11-10 00:56:59 +01:00
return 0
}
@objc
2018-12-18 00:48:15 +01:00
public var sourceFilenameBuilder : ( ) -> String ? = {
2018-11-10 00:56:59 +01:00
return " fake_file.dat "
}
@objc
2018-12-18 00:48:15 +01:00
public var captionBuilder : ( ) -> String ? = {
2018-11-10 00:56:59 +01:00
return nil
}
@objc
2018-12-18 00:48:15 +01:00
public var albumMessageIdBuilder : ( ) -> String ? = {
2018-11-10 00:56:59 +01:00
return nil
}
}
2018-10-16 20:04:10 +02:00
extension Array {
2018-12-18 00:48:15 +01:00
public func ows_randomElement ( ) -> Element ? {
2018-10-16 20:04:10 +02:00
guard self . count > 0 else {
return nil
}
let index = arc4random_uniform ( UInt32 ( self . count ) )
return self [ Int ( index ) ]
}
}
2018-10-16 23:09:25 +02:00
struct CommonGenerator {
2018-12-18 00:48:15 +01:00
static public var contactId : String {
2018-10-16 23:09:25 +02:00
let digits = [ " 0 " , " 1 " , " 2 " , " 3 " , " 4 " , " 5 " , " 6 " , " 7 " , " 8 " , " 9 " ]
2018-10-16 20:04:10 +02:00
let randomDigits = ( 0. . < 10 ) . map { _ in return digits . ows_randomElement ( ) ! }
2018-10-16 23:09:25 +02:00
return " +1 " . appending ( randomDigits . joined ( ) )
}
// B o d y C o n t e n t
static let sentences = [
" Lorem ipsum dolor sit amet, consectetur adipiscing elit. " ,
" Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse rutrum, nulla vitae pretium hendrerit, tellus turpis pharetra libero, vitae sodales tortor ante vel sem. " ,
" In a time of universal deceit - telling the truth is a revolutionary act. " ,
" If you want a vision of the future, imagine a boot stamping on a human face - forever. " ,
" Who controls the past controls the future. Who controls the present controls the past. " ,
" All animals are equal, but some animals are more equal than others. " ,
" War is peace. Freedom is slavery. Ignorance is strength. " ,
" All the war-propaganda, all the screaming and lies and hatred, comes invariably from people who are not fighting. " ,
" Political language. . . is designed to make lies sound truthful and murder respectable, and to give an appearance of solidity to pure wind. " ,
" The nationalist not only does not disapprove of atrocities committed by his own side, but he has a remarkable capacity for not even hearing about them. " ,
" Every generation imagines itself to be more intelligent than the one that went before it, and wiser than the one that comes after it. " ,
" War against a foreign country only happens when the moneyed classes think they are going to profit from it. " ,
" People have only as much liberty as they have the intelligence to want and the courage to take. " ,
" You cannot buy the revolution. You cannot make the revolution. You can only be the revolution. It is in your spirit, or it is nowhere. " ,
" That is what I have always understood to be the essence of anarchism: the conviction that the burden of proof has to be placed on authority, and that it should be dismantled if that burden cannot be met. " ,
" Ask for work. If they don't give you work, ask for bread. If they do not give you work or bread, then take bread. " ,
" Every society has the criminals it deserves. " ,
" Anarchism is founded on the observation that since few men are wise enough to rule themselves, even fewer are wise enough to rule others. " ,
" If you would know who controls you see who you may not criticise. " ,
" At one time in the world there were woods that no one owned. "
]
2018-12-18 00:48:15 +01:00
static public var word : String {
2018-10-16 23:09:25 +02:00
return String ( sentence . split ( separator : " " ) . first ! )
}
2018-12-18 00:48:15 +01:00
static public func words ( count : Int ) -> String {
2018-10-16 23:09:25 +02:00
var result : [ String ] = [ ]
while result . count < count {
let remaining = count - result . count
result += sentence . split ( separator : " " ) . prefix ( remaining ) . map { String ( $0 ) }
}
return result . joined ( separator : " " )
}
2018-12-18 00:48:15 +01:00
static public var sentence : String {
2018-10-16 20:04:10 +02:00
return sentences . ows_randomElement ( ) !
2018-10-16 23:09:25 +02:00
}
2018-12-18 00:48:15 +01:00
static public func sentences ( count : UInt ) -> [ String ] {
2018-10-16 23:09:25 +02:00
return ( 0. . < count ) . map { _ in sentence }
}
2018-12-18 00:48:15 +01:00
static public var paragraph : String {
2018-10-16 20:04:10 +02:00
let sentenceCount = UInt ( arc4random_uniform ( 7 ) + 2 )
2018-10-16 23:09:25 +02:00
return paragraph ( sentenceCount : sentenceCount )
}
2018-12-18 00:48:15 +01:00
static public func paragraph ( sentenceCount : UInt ) -> String {
2018-10-16 23:09:25 +02:00
return sentences ( count : sentenceCount ) . joined ( separator : " " )
}
}